Skip to content

Commit

Permalink
Merge pull request #7 from OriumNetwork/feature--ON-505
Browse files Browse the repository at this point in the history
ON-505: anonymous ERC7432 events
  • Loading branch information
karacurt authored Oct 25, 2023
2 parents d545cf1 + 82f0405 commit 4100b73
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 66 deletions.
14 changes: 11 additions & 3 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Account @entity {
}

type RoleAssignment @entity {
id: ID! # grantorAddress + tokenId + tokenAddress + granteeAddress + roleHash
id: ID! # rolesRegistryAddress + grantorAddress + tokenId + tokenAddress + granteeAddress + roleHash
role: Role!
nft: Nft!
grantor: Account!
Expand All @@ -28,15 +28,23 @@ type RoleAssignment @entity {
}

type Role @entity {
id: ID! # tokenId + tokenAddress + roleHash
id: ID! # rolesRegistryAddress + tokenId + tokenAddress + roleHash
rolesRegistry: RolesRegistry!
roleHash: Bytes!
nft: Nft!
roleAssignments: [RoleAssignment!] @derivedFrom(field: "role")
}

type RoleApproval @entity {
id: ID! # grantorAddress + operatorAddress + tokenAddress
id: ID! # rolesRegistryAddress + grantorAddress + operatorAddress + tokenAddress
rolesRegistry: RolesRegistry!
grantor: Account!
operator: Account!
tokenAddress: String!
}

type RolesRegistry @entity {
id: ID! # contractAddress
roles: [Role!] @derivedFrom(field: "rolesRegistry")
roleApprovals: [RoleApproval!] @derivedFrom(field: "rolesRegistry")
}
2 changes: 1 addition & 1 deletion src/erc7432/role/revoke-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function handleRoleRevoked(event: RoleRevoked): void {
return
}

const roleAssignmentId = generateRoleAssignmentId(revoker, grantee, nft, event.params._role)
const roleAssignmentId = generateRoleAssignmentId(event.address.toHex(), revoker, grantee, nft, event.params._role)
const roleAssignment = RoleAssignment.load(roleAssignmentId)
if (!roleAssignment) {
log.warning('[handleRoleRevoked] RoleAssignment {} does not exist, skipping...', [roleAssignmentId])
Expand Down
10 changes: 8 additions & 2 deletions src/erc7432/role/role-approval-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { log } from '@graphprotocol/graph-ts'

export function handleRoleApprovalForAll(event: RoleApprovalForAll): void {
const rolesRegistryAddress = event.address.toHex()
const grantorAddress = event.transaction.from.toHex()
const operatorAddress = event.params._operator.toHex()
const tokenAddress = event.params._tokenAddress.toHex()
Expand All @@ -17,13 +18,18 @@ export function handleRoleApprovalForAll(event: RoleApprovalForAll): void {
const operatorAccount = findOrCreateAccount(operatorAddress)

if (isApproved) {
const roleApproval = insertRoleApprovalIfNotExist(grantorAccount, operatorAccount, tokenAddress)
const roleApproval = insertRoleApprovalIfNotExist(
rolesRegistryAddress,
grantorAccount,
operatorAccount,
tokenAddress,
)
log.warning('[handleRoleApprovalForAll] Updated RoleAssignment Approval: {} Tx: {}', [
roleApproval.id,
event.transaction.hash.toHex(),
])
} else {
const roleApprovalId = generateRoleApprovalId(grantorAccount, operatorAccount, tokenAddress)
const roleApprovalId = generateRoleApprovalId(rolesRegistryAddress, grantorAccount, operatorAccount, tokenAddress)
deleteRoleApprovalIfExist(roleApprovalId)
log.warning('[handleRoleApprovalForAll] Removed RoleAssignment Approval: {} Tx: {}', [
roleApprovalId,
Expand Down
55 changes: 42 additions & 13 deletions src/utils/helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BigInt, Bytes, store } from '@graphprotocol/graph-ts'
import { Account, Nft, Role, RoleApproval, RoleAssignment } from '../../generated/schema'
import { Account, Nft, Role, RoleApproval, RoleAssignment, RolesRegistry } from '../../generated/schema'
import { RoleGranted } from '../../generated/ERC7432-Immutable-Roles/ERC7432'

export function findOrCreateAccount(id: string): Account {
Expand All @@ -25,8 +25,14 @@ export function generateNftId(tokenAddress: string, tokenId: string): string {
return tokenAddress + '-' + tokenId
}

export function generateRoleAssignmentId(grantor: Account, grantee: Account, nft: Nft, roleAssignment: Bytes): string {
return grantor.id + '-' + grantee.id + '-' + nft.id + '-' + roleAssignment.toHex()
export function generateRoleAssignmentId(
roleRegistryAddress: string,
grantor: Account,
grantee: Account,
nft: Nft,
roleAssignment: Bytes,
): string {
return roleRegistryAddress + '-' + grantor.id + '-' + grantee.id + '-' + nft.id + '-' + roleAssignment.toHex()
}

export function findOrCreateRoleAssignment(
Expand All @@ -35,12 +41,12 @@ export function findOrCreateRoleAssignment(
grantee: Account,
nft: Nft,
): RoleAssignment {
const roleAssignmentId = generateRoleAssignmentId(grantor, grantee, nft, event.params._role)
const roleAssignmentId = generateRoleAssignmentId(event.address.toHex(), grantor, grantee, nft, event.params._role)
let roleAssignment = RoleAssignment.load(roleAssignmentId)

if (!roleAssignment) {
roleAssignment = new RoleAssignment(roleAssignmentId)
roleAssignment.role = findOrCreateRole(nft, event.params._role).id
roleAssignment.role = findOrCreateRole(event.address.toHex(), nft, event.params._role).id
roleAssignment.nft = nft.id
roleAssignment.grantor = grantor.id
roleAssignment.grantee = grantee.id
Expand All @@ -55,36 +61,48 @@ export function findOrCreateRoleAssignment(
return roleAssignment
}

export function findOrCreateRole(nft: Nft, roleHash: Bytes): Role {
const roleId = generateRoleId(nft, roleHash)
export function findOrCreateRole(roleRegistryAddress: string, nft: Nft, roleHash: Bytes): Role {
const roleId = generateRoleId(roleRegistryAddress, nft, roleHash)
let role = Role.load(roleId)

if (!role) {
role = new Role(roleId)
role.roleHash = roleHash
role.nft = nft.id
role.rolesRegistry = findOrCreateRolesRegistry(roleRegistryAddress).id
role.save()
}

return role
}

export function generateRoleId(nft: Nft, roleHash: Bytes): string {
return nft.id + '-' + roleHash.toHex()
export function generateRoleId(roleRegistryAddress: string, nft: Nft, roleHash: Bytes): string {
return roleRegistryAddress + '-' + nft.id + '-' + roleHash.toHex()
}

export function generateRoleApprovalId(grantor: Account, operator: Account, tokenAddress: string): string {
return grantor.id + '-' + operator.id + '-' + tokenAddress.toLowerCase()
export function generateRoleApprovalId(
rolesRegistryAddress: string,
grantor: Account,
operator: Account,
tokenAddress: string,
): string {
return rolesRegistryAddress + '-' + grantor.id + '-' + operator.id + '-' + tokenAddress.toLowerCase()
}

export function insertRoleApprovalIfNotExist(grantor: Account, operator: Account, tokenAddress: string): RoleApproval {
const roleApprovalId = generateRoleApprovalId(grantor, operator, tokenAddress)
export function insertRoleApprovalIfNotExist(
rolesRegistryAddress: string,
grantor: Account,
operator: Account,
tokenAddress: string,
): RoleApproval {
const roleApprovalId = generateRoleApprovalId(rolesRegistryAddress, grantor, operator, tokenAddress)
let roleApproval = RoleApproval.load(roleApprovalId)
if (!roleApproval) {
roleApproval = new RoleApproval(roleApprovalId)
roleApproval.grantor = grantor.id
roleApproval.operator = operator.id
roleApproval.tokenAddress = tokenAddress.toLowerCase()
roleApproval.rolesRegistry = findOrCreateRolesRegistry(rolesRegistryAddress).id
roleApproval.save()
}
return roleApproval
Expand All @@ -96,3 +114,14 @@ export function deleteRoleApprovalIfExist(roleApprovalId: string): void {
store.remove('RoleApproval', roleApprovalId)
}
}

export function findOrCreateRolesRegistry(rolesRegistryAddress: string): RolesRegistry {
let rolesRegistry = RolesRegistry.load(rolesRegistryAddress)

if (!rolesRegistry) {
rolesRegistry = new RolesRegistry(rolesRegistryAddress)
rolesRegistry.save()
}

return rolesRegistry
}
2 changes: 0 additions & 2 deletions subgraph-goerli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ dataSources:
kind: ethereum
network: goerli
source:
address: '0xb2ad616e84e1ef7a9ed0fa3169aaf31ee51ea824'
abi: ERC7432
startBlock: 9815688
mapping:
kind: ethereum/events
apiVersion: 0.0.6
Expand Down
2 changes: 0 additions & 2 deletions subgraph-mumbai.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ dataSources:
kind: ethereum
network: mumbai
source:
address: '0xb2ad616e84e1ef7a9ed0fa3169aaf31ee51ea824'
abi: ERC7432
startBlock: 40877849
mapping:
kind: ethereum/events
apiVersion: 0.0.6
Expand Down
2 changes: 0 additions & 2 deletions subgraph-polygon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ dataSources:
kind: ethereum
network: matic
source:
address: '0xb2ad616e84e1ef7a9ed0fa3169aaf31ee51ea824'
abi: ERC7432
startBlock: 48672001
mapping:
kind: ethereum/events
apiVersion: 0.0.6
Expand Down
11 changes: 6 additions & 5 deletions tests/erc7432/approval-handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { assert, describe, test, clearStore, afterEach } from 'matchstick-as'
import { createNewRoleApprovalForAllEvent } from '../helpers/events'
import { validateRoleApproval, createMockRoleApproval } from '../helpers/entities'
import { Addresses } from '../helpers/contants'
import { Addresses, ZERO_ADDRESS } from '../helpers/contants'
import { handleRoleApprovalForAll } from '../../src/erc7432'

const grantor = Addresses[0]
const operator = Addresses[1]
const tokenAddress = Addresses[2]
const rolesRegistryAddress = ZERO_ADDRESS

describe('ERC-7432 RoleApprovalForAll Handler', () => {
afterEach(() => {
Expand All @@ -15,7 +16,7 @@ describe('ERC-7432 RoleApprovalForAll Handler', () => {

describe('When RoleApproval exists', () => {
test('should remove approval when is set to false', () => {
createMockRoleApproval(grantor, operator, tokenAddress)
createMockRoleApproval(grantor, operator, tokenAddress, rolesRegistryAddress)
assert.entityCount('RoleApproval', 1)

const event = createNewRoleApprovalForAllEvent(grantor, operator, tokenAddress, false)
Expand All @@ -25,14 +26,14 @@ describe('ERC-7432 RoleApprovalForAll Handler', () => {
})

test('should not do anything when is set to true', () => {
createMockRoleApproval(grantor, operator, tokenAddress)
createMockRoleApproval(grantor, operator, tokenAddress, rolesRegistryAddress)
assert.entityCount('RoleApproval', 1)

const event = createNewRoleApprovalForAllEvent(grantor, operator, tokenAddress, true)
handleRoleApprovalForAll(event)

assert.entityCount('RoleApproval', 1)
validateRoleApproval(grantor, operator, tokenAddress)
validateRoleApproval(rolesRegistryAddress, grantor, operator, tokenAddress)
})
})

Expand All @@ -53,7 +54,7 @@ describe('ERC-7432 RoleApprovalForAll Handler', () => {
handleRoleApprovalForAll(event)

assert.entityCount('RoleApproval', 1)
validateRoleApproval(grantor, operator, tokenAddress)
validateRoleApproval(rolesRegistryAddress, grantor, operator, tokenAddress)
})
})
})
39 changes: 32 additions & 7 deletions tests/erc7432/grant-handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { assert, describe, test, clearStore, afterEach } from 'matchstick-as'
import { createNewRoleGrantedEvent } from '../helpers/events'
import { handleRoleGranted } from '../../src/erc7432'
import { Addresses } from '../helpers/contants'
import { Addresses, ZERO_ADDRESS } from '../helpers/contants'
import { BigInt, Bytes } from '@graphprotocol/graph-ts'
import { createMockAccount, createMockNft, validateRole } from '../helpers/entities'
import { Account } from '../../generated/schema'
Expand All @@ -14,6 +14,7 @@ const grantor = Addresses[2]
const revocable = true
const data = Bytes.fromUTF8('0x1234567890')
const expirationDate = BigInt.fromI32(99999)
const rolesRegistry = ZERO_ADDRESS

describe('ERC-7432 RoleGranted Handler', () => {
afterEach(() => {
Expand Down Expand Up @@ -133,9 +134,33 @@ describe('ERC-7432 RoleGranted Handler', () => {
assert.entityCount('Account', 3)

const grantorAccount = new Account(grantor)
validateRole(grantorAccount, new Account(Addresses[0]), nft, RoleAssignmentId, expirationDate, data)
validateRole(grantorAccount, new Account(Addresses[1]), nft, RoleAssignmentId, expirationDate, data)
validateRole(grantorAccount, new Account(Addresses[2]), nft, RoleAssignmentId, expirationDate, data)
validateRole(
grantorAccount,
new Account(Addresses[0]),
nft,
RoleAssignmentId,
expirationDate,
data,
event1.address.toHex(),
)
validateRole(
grantorAccount,
new Account(Addresses[1]),
nft,
RoleAssignmentId,
expirationDate,
data,
event2.address.toHex(),
)
validateRole(
grantorAccount,
new Account(Addresses[2]),
nft,
RoleAssignmentId,
expirationDate,
data,
event3.address.toHex(),
)
})

test('should grant multiple roles for different NFTs', () => {
Expand Down Expand Up @@ -189,8 +214,8 @@ describe('ERC-7432 RoleGranted Handler', () => {
assert.entityCount('Account', 3)

const grantorAccount = new Account(grantor)
validateRole(grantorAccount, new Account(Addresses[0]), nft1, RoleAssignmentId, expirationDate, data)
validateRole(grantorAccount, new Account(Addresses[1]), nft2, RoleAssignmentId, expirationDate, data)
validateRole(grantorAccount, new Account(Addresses[2]), nft3, RoleAssignmentId, expirationDate, data)
validateRole(grantorAccount, new Account(Addresses[0]), nft1, RoleAssignmentId, expirationDate, data, rolesRegistry)
validateRole(grantorAccount, new Account(Addresses[1]), nft2, RoleAssignmentId, expirationDate, data, rolesRegistry)
validateRole(grantorAccount, new Account(Addresses[2]), nft3, RoleAssignmentId, expirationDate, data, rolesRegistry)
})
})
Loading

0 comments on commit 4100b73

Please sign in to comment.