From a58cf6be2b4f940e4e3f0af830db1d54f88df11c Mon Sep 17 00:00:00 2001 From: 0xdavinchee <0xdavinchee@gmail.com> Date: Tue, 12 Mar 2024 15:31:56 +0200 Subject: [PATCH] [SUBGRAPH] approval mapping (#1878) * approval mapping * missing addresses * missing addresses cont. * no-op, trigger build * fix tests --------- Co-authored-by: Kaspar Kallas --- packages/subgraph/schema.graphql | 98 +++++++++++++++---- packages/subgraph/src/mappings/flowNFT.ts | 8 +- packages/subgraph/src/mappings/host.ts | 14 +-- packages/subgraph/src/mappings/resolver.ts | 6 +- packages/subgraph/src/mappings/superToken.ts | 12 +++ .../src/mappings/superTokenFactory.ts | 2 +- .../src/mappings/superfluidGovernance.ts | 17 ++-- .../superToken/event/superToken.event.test.ts | 30 +++++- .../tests/superToken/superToken.helper.ts | 14 +++ 9 files changed, 159 insertions(+), 42 deletions(-) diff --git a/packages/subgraph/schema.graphql b/packages/subgraph/schema.graphql index 1627c06aa4..5820aba5fb 100644 --- a/packages/subgraph/schema.graphql +++ b/packages/subgraph/schema.graphql @@ -830,7 +830,8 @@ type AgreementClassRegisteredEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `code` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -849,7 +850,8 @@ type AgreementClassUpdatedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `code` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -868,7 +870,8 @@ type AppRegisteredEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `app` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -889,7 +892,9 @@ type GovernanceReplacedEvent implements Event @entity(immutable: true) { order: BigInt! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `oldGovernance` + addresses[1] = `newGovernance` """ addresses: [Bytes!]! oldGovernance: Bytes! @@ -905,7 +910,8 @@ type JailEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `app` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -924,7 +930,8 @@ type SuperTokenFactoryUpdatedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `newFactory` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -942,7 +949,9 @@ type SuperTokenLogicUpdatedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `token` + addresses[1] = `code` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -963,7 +972,9 @@ type RoleAdminChangedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `previousAdminRole` + addresses[1] = `newAdminRole` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -983,7 +994,9 @@ type RoleGrantedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `account` + addresses[1] = `sender` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1003,7 +1016,9 @@ type RoleRevokedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `account` + addresses[1] = `sender` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1057,7 +1072,10 @@ type CFAv1LiquidationPeriodChangedEvent implements Event governanceAddress: Bytes! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `governanceAddress` + addresses[1] = `host` + addresses[2] = `superToken` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1083,7 +1101,10 @@ type ConfigChangedEvent implements Event @entity(immutable: true) { governanceAddress: Bytes! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `governanceAddress` + addresses[1] = `host` + addresses[2] = `superToken` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1110,7 +1131,11 @@ type RewardAddressChangedEvent implements Event @entity(immutable: true) { governanceAddress: Bytes! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `governanceAddress` + addresses[1] = `host` + addresses[2] = `superToken` + addresses[3] = `rewardAddress` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1136,7 +1161,10 @@ type PPPConfigurationChangedEvent implements Event @entity(immutable: true) { governanceAddress: Bytes! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `governanceAddress` + addresses[1] = `host` + addresses[2] = `superToken` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1164,7 +1192,10 @@ type SuperTokenMinimumDepositChangedEvent implements Event governanceAddress: Bytes! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `governanceAddress` + addresses[1] = `host` + addresses[2] = `superToken` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1190,7 +1221,11 @@ type TrustedForwarderChangedEvent implements Event @entity(immutable: true) { governanceAddress: Bytes! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `governanceAddress` + addresses[1] = `host` + addresses[2] = `superToken` + addresses[3] = `forwarder` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1468,20 +1503,39 @@ type ApprovalEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `isNFTApproval` ? `nft address` : `token` (superToken) + addresses[1] = `owner` + addresses[2] = `to` """ addresses: [Bytes!]! blockNumber: BigInt! logIndex: BigInt! order: BigInt! + """ + The address that will be granting allowance to transfer ERC20/NFT. + """ owner: Account! """ - The address that will be granted allowance to transfer the NFT. + The address that will be granted allowance to transfer ERC20/NFT. """ to: Account! + + """ + Indicates whether the event was emitted for the approval of an NFT. + """ + isNFTApproval: Boolean! + + """ + If `amount` is non-zero, this event was emitted for the approval of an ERC20. + Tne amount of ERC20 tokens that will be granted allowance to transfer. """ + amount: BigInt! + + """ + If `tokenId` is non-zero, this event was emitted for the approval of an NFT. The id of the NFT that will be granted allowance to transfer. The id is: uint256(keccak256(abi.encode(block.chainid, superToken, sender, receiver))) """ @@ -1497,7 +1551,10 @@ type ApprovalForAllEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = NFT address + addresses[1] = `owner` + addresses[2] = `operator` """ addresses: [Bytes!]! blockNumber: BigInt! @@ -1590,7 +1647,8 @@ type SuperTokenLogicCreatedEvent implements Event @entity(immutable: true) { name: String! """ - Empty addresses array. + Contains the addresses that were impacted by this event: + addresses[0] = `tokenLogic` """ addresses: [Bytes!]! blockNumber: BigInt! diff --git a/packages/subgraph/src/mappings/flowNFT.ts b/packages/subgraph/src/mappings/flowNFT.ts index a070abf8dd..2124988e1e 100644 --- a/packages/subgraph/src/mappings/flowNFT.ts +++ b/packages/subgraph/src/mappings/flowNFT.ts @@ -10,15 +10,17 @@ import { MetadataUpdateEvent, TransferEvent, } from "../../generated/schema"; -import { createEventID, initializeEventEntity } from "../utils"; +import { BIG_INT_ONE, createEventID, initializeEventEntity } from "../utils"; export function handleApproval(event: Approval): void { const eventId = createEventID("Approval", event); const ev = new ApprovalEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.owner, event.params.approved]); ev.owner = event.params.owner.toHex(); ev.to = event.params.approved.toHex(); ev.tokenId = event.params.tokenId; + ev.amount = BIG_INT_ONE.neg(); + ev.isNFTApproval = true; ev.save(); } @@ -26,7 +28,7 @@ export function handleApproval(event: Approval): void { export function handleApprovalForAll(event: ApprovalForAll): void { const eventId = createEventID("ApprovalForAll", event); const ev = new ApprovalForAllEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.owner, event.params.operator]); ev.owner = event.params.owner.toHex(); ev.operator = event.params.operator.toHex(); ev.approved = event.params.approved; diff --git a/packages/subgraph/src/mappings/host.ts b/packages/subgraph/src/mappings/host.ts index 7b877d3ff4..738afd49d0 100644 --- a/packages/subgraph/src/mappings/host.ts +++ b/packages/subgraph/src/mappings/host.ts @@ -25,7 +25,7 @@ import { SuperfluidGovernance } from "../../generated/templates"; export function handleGovernanceReplaced(event: GovernanceReplaced): void { const eventId = createEventID("GovernanceReplaced", event); const ev = new GovernanceReplacedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.oldGov, event.params.newGov]); ev.oldGovernance = event.params.oldGov; ev.newGovernance = event.params.newGov; ev.save(); @@ -42,7 +42,7 @@ export function handleAgreementClassRegistered( ): void { const eventId = createEventID("AgreementClassRegistered", event); const ev = new AgreementClassRegisteredEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.code]); ev.agreementType = event.params.agreementType; ev.code = event.params.code; ev.save(); @@ -55,7 +55,7 @@ export function handleAgreementClassUpdated( ): void { const eventId = createEventID("AgreementClassUpdated", event); const ev = new AgreementClassUpdatedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.code]); ev.agreementType = event.params.agreementType; ev.code = event.params.code; @@ -70,7 +70,7 @@ export function handleSuperTokenFactoryUpdated( ): void { const eventId = createEventID("SuperTokenFactoryUpdated", event); const ev = new SuperTokenFactoryUpdatedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.newFactory]); ev.newFactory = event.params.newFactory; ev.save(); @@ -81,7 +81,7 @@ export function handleSuperTokenLogicUpdated( ): void { const eventId = createEventID("SuperTokenLogicUpdated", event); const ev = new SuperTokenLogicUpdatedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.token, event.params.code]); ev.token = event.params.token; ev.code = event.params.code; @@ -90,7 +90,7 @@ export function handleSuperTokenLogicUpdated( export function handleAppRegistered(event: AppRegistered): void { const ev = new AppRegisteredEvent(createEventID("AppRegistered", event)); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.app]); ev.app = event.params.app; ev.save(); @@ -98,7 +98,7 @@ export function handleAppRegistered(event: AppRegistered): void { export function handleJail(event: Jail): void { const ev = new JailEvent(createEventID("Jail", event)); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.app]); ev.app = event.params.app; ev.reason = event.params.reason; diff --git a/packages/subgraph/src/mappings/resolver.ts b/packages/subgraph/src/mappings/resolver.ts index 69a0d3dc26..706647abc4 100644 --- a/packages/subgraph/src/mappings/resolver.ts +++ b/packages/subgraph/src/mappings/resolver.ts @@ -18,7 +18,7 @@ import { createEventID, initializeEventEntity, ZERO_ADDRESS } from "../utils"; export function handleRoleAdminChanged(event: RoleAdminChanged): void { const eventId = createEventID("RoleAdminChanged", event); const ev = new RoleAdminChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.previousAdminRole, event.params.newAdminRole]); ev.role = event.params.role; ev.previousAdminRole = event.params.previousAdminRole; @@ -29,7 +29,7 @@ export function handleRoleAdminChanged(event: RoleAdminChanged): void { export function handleRoleGranted(event: RoleGranted): void { const eventId = createEventID("RoleGranted", event); const ev = new RoleGrantedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.account, event.params.sender]); ev.role = event.params.role; ev.account = event.params.account; @@ -39,7 +39,7 @@ export function handleRoleGranted(event: RoleGranted): void { export function handleRoleRevoked(event: RoleRevoked): void { const eventId = createEventID("RoleRevoked", event); const ev = new RoleRevokedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.account, event.params.sender]); ev.role = event.params.role; ev.account = event.params.account; diff --git a/packages/subgraph/src/mappings/superToken.ts b/packages/subgraph/src/mappings/superToken.ts index a6e10d496d..18be4b2050 100644 --- a/packages/subgraph/src/mappings/superToken.ts +++ b/packages/subgraph/src/mappings/superToken.ts @@ -12,6 +12,7 @@ import { import { AgreementLiquidatedByEvent, AgreementLiquidatedV2Event, + ApprovalEvent, BurnedEvent, MintedEvent, SentEvent, @@ -452,6 +453,17 @@ function _createTransferEventEntity(event: Transfer): void { } export function handleApproval(event: Approval): void { + const eventId = createEventID("Approval", event); + const ev = new ApprovalEvent(eventId); + initializeEventEntity(ev, event, [event.address, event.params.owner, event.params.spender]); + ev.owner = event.params.owner.toHex(); + ev.to = event.params.spender.toHex(); + ev.tokenId = BIG_INT_ZERO; + ev.amount = event.params.value; + ev.isNFTApproval = false; + + ev.save(); + // The entity named `FlowOperators` which currently holds all the user access and approval settings will be renamed to `AccessSettings`. const flowOperator = getOrInitFlowOperator( event.block, diff --git a/packages/subgraph/src/mappings/superTokenFactory.ts b/packages/subgraph/src/mappings/superTokenFactory.ts index d8d3bdf701..e65b939daa 100644 --- a/packages/subgraph/src/mappings/superTokenFactory.ts +++ b/packages/subgraph/src/mappings/superTokenFactory.ts @@ -59,7 +59,7 @@ export function handleSuperTokenLogicCreated( } const eventId = createEventID("SuperTokenLogicCreated", event); const ev = new SuperTokenLogicCreatedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.params.tokenLogic]); ev.tokenLogic = event.params.tokenLogic; ev.save(); diff --git a/packages/subgraph/src/mappings/superfluidGovernance.ts b/packages/subgraph/src/mappings/superfluidGovernance.ts index bbee404b60..a8432dc228 100644 --- a/packages/subgraph/src/mappings/superfluidGovernance.ts +++ b/packages/subgraph/src/mappings/superfluidGovernance.ts @@ -21,7 +21,7 @@ import { getOrInitTokenGovernanceConfig } from "../mappingHelpers"; export function handleConfigChanged(event: ConfigChanged): void { const eventId = createEventID("ConfigChanged", event); const ev = new ConfigChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.host, event.params.superToken]) ev.governanceAddress = event.address; ev.host = event.params.host; @@ -35,7 +35,7 @@ export function handleConfigChanged(event: ConfigChanged): void { export function handleRewardAddressChanged(event: RewardAddressChanged): void { const eventId = createEventID("RewardAddressChanged", event); const ev = new RewardAddressChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.host, event.params.superToken, event.params.rewardAddress]); ev.governanceAddress = event.address; ev.host = event.params.host; @@ -66,7 +66,7 @@ export function handleCFAv1LiquidationPeriodChanged( ): void { const eventId = createEventID("CFAv1LiquidationPeriodChanged", event); const ev = new CFAv1LiquidationPeriodChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.host, event.params.superToken]); ev.governanceAddress = event.address; ev.host = event.params.host; @@ -91,7 +91,7 @@ export function handlePPPConfigurationChanged( ): void { const eventId = createEventID("PPPConfigurationChanged", event); const ev = new PPPConfigurationChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.host, event.params.superToken]); ev.governanceAddress = event.address; ev.host = event.params.host; @@ -118,7 +118,12 @@ export function handleTrustedForwarderChanged( ): void { const eventId = createEventID("TrustedForwarderChanged", event); const ev = new TrustedForwarderChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [ + event.address, + event.params.host, + event.params.superToken, + event.params.forwarder, + ]); ev.governanceAddress = event.address; ev.host = event.params.host; @@ -134,7 +139,7 @@ export function handleSuperTokenMinimumDepositChanged( ): void { const eventId = createEventID("SuperTokenMinimumDepositChanged", event); const ev = new SuperTokenMinimumDepositChangedEvent(eventId); - initializeEventEntity(ev, event, []); + initializeEventEntity(ev, event, [event.address, event.params.host, event.params.superToken]); ev.governanceAddress = event.address; ev.host = event.params.host; diff --git a/packages/subgraph/tests/superToken/event/superToken.event.test.ts b/packages/subgraph/tests/superToken/event/superToken.event.test.ts index f515b4165a..b04f280ba2 100644 --- a/packages/subgraph/tests/superToken/event/superToken.event.test.ts +++ b/packages/subgraph/tests/superToken/event/superToken.event.test.ts @@ -9,6 +9,7 @@ import { import { handleAgreementLiquidatedBy, handleAgreementLiquidatedV2, + handleApproval, handleBurned, handleMinted, handleSent, @@ -18,7 +19,7 @@ import { } from "../../../src/mappings/superToken"; import { BIG_INT_ONE, BIG_INT_ZERO, encode, ZERO_ADDRESS } from "../../../src/utils"; import { assertEmptyTokenStatisticProperties, assertEventBaseProperties, assertTokenStatisticProperties } from "../../assertionHelpers"; -import { alice, bob, cfaV1Address, charlie, DEFAULT_DECIMALS, delta, FAKE_INITIAL_BALANCE, maticXName, maticXSymbol } from "../../constants"; +import { alice, bob, cfaV1Address, charlie, DEFAULT_DECIMALS, delta, FAKE_INITIAL_BALANCE, FALSE, maticXName, maticXSymbol, TRUE } from "../../constants"; import { getETHAddress, getETHUnsignedBigInt, stringToBytes } from "../../converters"; import { createStream, createStreamRevision } from "../../mockedEntities"; import { mockedGetAppManifest, mockedGetHost, mockedHandleSuperTokenInitRPCCalls, mockedRealtimeBalanceOf } from "../../mockedFunctions"; @@ -28,6 +29,7 @@ import { createBurnedEvent, createMintedEvent, createSentEvent, + createSuperTokenApprovalEvent, createTokenDowngradedEvent, createTokenUpgradedEvent, createTransferEvent, @@ -337,6 +339,30 @@ describe("SuperToken Mapper Unit Tests", () => { assert.fieldEquals("TokenDowngradedEvent", id, "amount", amount.toString()); }); + test("handleApproval() - Should create a new ApprovalEvent entity", () => { + const owner = alice; + const spender = bob; + const value = BigInt.fromI32(100); + + const superTokenApprovalEvent = createSuperTokenApprovalEvent( + owner, + spender, + value + ); + + handleApproval(superTokenApprovalEvent); + + const id = assertEventBaseProperties( + superTokenApprovalEvent, + "Approval" + ); + assert.fieldEquals("ApprovalEvent", id, "owner", owner); + assert.fieldEquals("ApprovalEvent", id, "to", spender); + assert.fieldEquals("ApprovalEvent", id, "amount", value.toString()); + assert.fieldEquals("ApprovalEvent", id, "isNFTApproval", FALSE); + assert.fieldEquals("ApprovalEvent", id, "tokenId", "0"); + }); + test("handleTransfer() - Should create a new TransferEvent entity", () => { const from = alice; const to = bob; @@ -480,7 +506,7 @@ describe("SuperToken Mapper Unit Tests", () => { "operatorData", operatorData.toHexString() ); - }); + }); test("TokenStatistic::totalNumberOfHolders should decrease its count when a user transfers tokens and the balance reaches 0.", () => { const from = alice; diff --git a/packages/subgraph/tests/superToken/superToken.helper.ts b/packages/subgraph/tests/superToken/superToken.helper.ts index a8f9d82ae3..4ac930cdf8 100644 --- a/packages/subgraph/tests/superToken/superToken.helper.ts +++ b/packages/subgraph/tests/superToken/superToken.helper.ts @@ -77,6 +77,20 @@ export function createTokenUpgradedEvent( return newTokenUpgradedEvent; } +export function createSuperTokenApprovalEvent( + owner: string, + spender: string, + value: BigInt +): Approval { + const newApprovalEvent = changetype(newMockEvent()); + newApprovalEvent.parameters = new Array(); + newApprovalEvent.parameters.push(getAddressEventParam("owner", owner)); + newApprovalEvent.parameters.push(getAddressEventParam("spender", spender)); + newApprovalEvent.parameters.push(getBigIntEventParam("value", value)); + + return newApprovalEvent; +} + export function createTokenDowngradedEvent( account: string, amount: BigInt