From 772b723d8accee6b00e0d446bc9059ff9b9f465d Mon Sep 17 00:00:00 2001 From: Alex Coseru Date: Fri, 18 Feb 2022 13:09:18 +0200 Subject: [PATCH] roles (#336) * roles --- schema.graphql | 12 ++- src/mappings/dispenser.ts | 2 +- src/mappings/erc20Templates.ts | 90 ++++++++++++++-- src/mappings/erc721Factory.ts | 16 ++- src/mappings/fixedRateExchange.ts | 15 ++- src/mappings/nftUpdate.ts | 148 ++++++++++++++++++++++++++- src/mappings/pool.ts | 13 +-- src/mappings/utils/dispenserUtils.ts | 3 +- src/mappings/utils/tokenUtils.ts | 48 +++++++-- subgraph.template.yaml | 45 +++++++- 10 files changed, 338 insertions(+), 54 deletions(-) diff --git a/schema.graphql b/schema.graphql index bcbce6c..7ecd050 100644 --- a/schema.graphql +++ b/schema.graphql @@ -11,11 +11,14 @@ type Token @entity { "address of ERC721 that owns the token, valid only for datatokens" nft: Nft - "array of addresses with minter role, can be user wallet address, dispenser etc." - minter: [User!] + "array of addresses with minter role" + minter: [String!] - "TODO: maybe we change name , depends on audit results . It's the address that collects the payments (NOT fees)" - feeManager: String + "array of addresses with payment manager minter role" + paymentManager: [String!] + + "address that collects the payments (NOT fees)" + paymentCollector: String "address of the market where the datatoken was created. This address collects market fees." publishMarketFeeAddress: String @@ -277,7 +280,6 @@ type User @entity { id: ID! sharesOwned: [PoolShare!] @derivedFrom(field: "user") tokenBalancesOwned: [TokenValuePair!] - tokensOwned: [Token!] @derivedFrom(field: "minter") poolTransactions: [PoolTransaction!] @derivedFrom(field: "user") orders: [Order!] @derivedFrom(field: "payer") freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by") diff --git a/src/mappings/dispenser.ts b/src/mappings/dispenser.ts index 760e93f..ded8220 100644 --- a/src/mappings/dispenser.ts +++ b/src/mappings/dispenser.ts @@ -16,7 +16,7 @@ import { getUser } from './utils/userUtils' export function handleNewDispenser(event: DispenserCreated): void { const dispenser = new Dispenser(event.params.datatokenAddress.toHex()) - const token = getToken(event.params.datatokenAddress.toHex()) + const token = getToken(event.params.datatokenAddress, false) dispenser.token = token.id dispenser.owner = event.params.owner.toHexString() diff --git a/src/mappings/erc20Templates.ts b/src/mappings/erc20Templates.ts index 8062f29..a7887bf 100644 --- a/src/mappings/erc20Templates.ts +++ b/src/mappings/erc20Templates.ts @@ -4,7 +4,12 @@ import { NewPaymentCollector, OrderStarted, PublishMarketFee, - PublishMarketFeeChanged + PublishMarketFeeChanged, + AddedMinter, + AddedPaymentManager, + RemovedMinter, + RemovedPaymentManager, + CleanedPermissions } from '../@types/templates/ERC20Template/ERC20Template' import { integer } from './utils/constants' @@ -30,7 +35,7 @@ export function handleOrderStarted(event: OrderStarted): void { ) ) - const token = getToken(event.address.toHex()) + const token = getToken(event.address, true) order.datatoken = token.id token.orderCount = token.orderCount.plus(integer.ONE) @@ -74,12 +79,11 @@ export function handleOrderStarted(event: OrderStarted): void { } } -export function handleNewPaymentCollector(event: NewPaymentCollector): void {} export function handlePublishMarketFee(event: PublishMarketFee): void {} export function handlePublishMarketFeeChanged( event: PublishMarketFeeChanged ): void { - const token = getToken(event.address.toHex()) + const token = getToken(event.address, true) if (token != null) { token.publishMarketFeeAddress = event.params.PublishMarketFeeAddress.toHexString() @@ -89,8 +93,8 @@ export function handlePublishMarketFeeChanged( if ( token.publishMarketFeeToken != '0x0000000000000000000000000000000000000000' - ){ - const token = getToken(event.params.PublishMarketFeeToken.toHexString()) + ) { + const token = getToken(event.params.PublishMarketFeeToken, false) decimals = BigInt.fromI32(token.decimals).toI32() } token.publishMarketFeeAmmount = weiToDecimal( @@ -101,6 +105,80 @@ export function handlePublishMarketFeeChanged( // TODO - shold we have a history } } + +// roles +// roles +export function handleAddedMinter(event: AddedMinter): void { + const token = getToken(event.address, true) + let existingRoles: string[] + if (!token.minter) existingRoles = [] + else existingRoles = token.minter as string[] + if (!existingRoles.includes(event.params.user.toHexString())) + existingRoles.push(event.params.user.toHexString()) + token.minter = existingRoles + token.save() +} + +export function handleRemovedMinter(event: RemovedMinter): void { + const token = getToken(event.address, true) + const newList: string[] = [] + let existingRoles: string[] + if (!token.minter) existingRoles = [] + else existingRoles = token.minter as string[] + if (!existingRoles || existingRoles.length < 1) return + while (existingRoles.length > 0) { + const role = existingRoles.shift().toString() + if (!role) break + if (role !== event.params.user.toHexString()) newList.push(role) + } + token.minter = newList + token.save() +} + +export function handleAddedPaymentManager(event: AddedPaymentManager): void { + const token = getToken(event.address, true) + let existingRoles: string[] + if (!token.paymentManager) existingRoles = [] + else existingRoles = token.paymentManager as string[] + if (!existingRoles.includes(event.params.user.toHexString())) + existingRoles.push(event.params.user.toHexString()) + token.paymentManager = existingRoles + token.save() +} +export function handleRemovedPaymentManager( + event: RemovedPaymentManager +): void { + const token = getToken(event.address, true) + const newList: string[] = [] + let existingRoles: string[] + if (!token.paymentManager) existingRoles = [] + else existingRoles = token.paymentManager as string[] + if (!existingRoles || existingRoles.length < 1) return + while (existingRoles.length > 0) { + const role = existingRoles.shift().toString() + if (!role) break + if (role !== event.params.user.toHexString()) newList.push(role) + } + token.paymentManager = newList + token.save() +} +export function handleCleanedPermissions(event: CleanedPermissions): void { + const token = getToken(event.address, true) + const newList: string[] = [] + token.paymentManager = newList + token.minter = newList + const nft = Nft.load(token.nft as string) + if (nft) token.paymentCollector = nft.owner + else token.paymentCollector = '0x0000000000000000000000000000000000000000' + token.save() +} + +export function handleNewPaymentCollector(event: NewPaymentCollector): void { + const token = getToken(event.address, true) + token.paymentCollector = event.params._newPaymentCollector.toHexString() + token.save() +} + // export function handlePublishMarketFees(event: PublishMarketFees): void { // const order = Order.load( // getOrderId( diff --git a/src/mappings/erc721Factory.ts b/src/mappings/erc721Factory.ts index 6fc5f69..b6345e0 100644 --- a/src/mappings/erc721Factory.ts +++ b/src/mappings/erc721Factory.ts @@ -1,16 +1,15 @@ import { log } from '@graphprotocol/graph-ts' import { NFTCreated, TokenCreated } from '../@types/ERC721Factory/ERC721Factory' -import { Nft, Token } from '../@types/schema' -import { ERC20Template, ERC721Template } from '../@types/templates' import { decimal } from './utils/constants' import { weiToDecimal } from './utils/generic' -import { addDatatoken, addNft } from './utils/globalUtils' + import { getUser } from './utils/userUtils' +import { getToken, getNftToken } from './utils/tokenUtils' export function handleNftCreated(event: NFTCreated): void { log.warning('nft handleNftCreated {}', [event.params.tokenURI.toString()]) - const nft = new Nft(event.params.newTokenAddress.toHexString()) - ERC721Template.create(event.params.newTokenAddress) + // const nft = new Nft(event.params.newTokenAddress.toHexString()) + const nft = getNftToken(event.params.newTokenAddress) const user = getUser(event.params.admin.toHexString()) nft.owner = user.id nft.address = event.params.newTokenAddress.toHexString() @@ -21,13 +20,13 @@ export function handleNftCreated(event: NFTCreated): void { nft.tx = event.transaction.hash.toHex() nft.block = event.block.number.toI32() - addNft() nft.save() } export function handleNewToken(event: TokenCreated): void { - const token = new Token(event.params.newTokenAddress.toHexString()) - ERC20Template.create(event.params.newTokenAddress) + const token = getToken(event.params.newTokenAddress, true) + // const token = new Token(event.params.newTokenAddress.toHexString()) + token.isDatatoken = true token.address = event.params.newTokenAddress.toHexString() token.createdTimestamp = event.block.timestamp.toI32() @@ -43,5 +42,4 @@ export function handleNewToken(event: TokenCreated): void { token.cap = weiToDecimal(event.params.cap.toBigDecimal(), 18) token.save() - addDatatoken() } diff --git a/src/mappings/fixedRateExchange.ts b/src/mappings/fixedRateExchange.ts index 0e8a89f..8805871 100644 --- a/src/mappings/fixedRateExchange.ts +++ b/src/mappings/fixedRateExchange.ts @@ -1,4 +1,4 @@ -import { BigInt } from '@graphprotocol/graph-ts' +import { BigInt, Address } from '@graphprotocol/graph-ts' import { ExchangeActivated, ExchangeAllowedSwapperChanged, @@ -26,12 +26,8 @@ export function handleExchangeCreated(event: ExchangeCreated): void { ) const user = getUser(event.params.exchangeOwner.toHexString()) fixedRateExchange.owner = user.id - fixedRateExchange.datatoken = getToken( - event.params.datatoken.toHexString() - ).id - fixedRateExchange.baseToken = getToken( - event.params.baseToken.toHexString() - ).id + fixedRateExchange.datatoken = getToken(event.params.datatoken, true).id + fixedRateExchange.baseToken = getToken(event.params.baseToken, false).id fixedRateExchange.active = false fixedRateExchange.price = weiToDecimal( @@ -169,7 +165,10 @@ export function handleSwap(event: Swapped): void { swap.by = getUser(event.params.by.toHex()).id // we need to fetch the decimals of the base token - const baseToken = getToken(fixedRateExchange.baseToken) + const baseToken = getToken( + Address.fromString(fixedRateExchange.baseToken), + false + ) swap.baseTokenAmount = weiToDecimal( event.params.baseTokenSwappedAmount.toBigDecimal(), BigInt.fromI32(baseToken.decimals).toI32() diff --git a/src/mappings/nftUpdate.ts b/src/mappings/nftUpdate.ts index e3c486e..782e2c2 100644 --- a/src/mappings/nftUpdate.ts +++ b/src/mappings/nftUpdate.ts @@ -3,14 +3,25 @@ import { MetadataCreated, MetadataState, MetadataUpdated, - TokenURIUpdate + TokenURIUpdate, + AddedManager, + AddedTo725StoreList, + AddedToCreateERC20List, + AddedToMetadataList, + RemovedFrom725StoreList, + RemovedFromCreateERC20List, + RemovedFromMetadataList, + RemovedManager, + CleanedPermissions } from '../@types/templates/ERC721Template/ERC721Template' import { NftUpdateType } from './utils/constants' +import { getNftToken } from './utils/tokenUtils' + function getId(tx: string, nftAddress: string): string { return `${tx}-${nftAddress}` } -export function handleCreated(event: MetadataCreated): void { +export function handleMetadataCreated(event: MetadataCreated): void { const nftAddress = event.address.toHex() const nft = Nft.load(nftAddress) if (!nft) return @@ -37,7 +48,7 @@ export function handleCreated(event: MetadataCreated): void { nft.save() } -export function handleUpdated(event: MetadataUpdated): void { +export function handleMetadataUpdated(event: MetadataUpdated): void { const nftAddress = event.address.toHex() const nft = Nft.load(nftAddress) if (!nft) return @@ -60,7 +71,7 @@ export function handleUpdated(event: MetadataUpdated): void { nft.save() } -export function handleState(event: MetadataState): void { +export function handleMetadataState(event: MetadataState): void { const nftAddress = event.address.toHex() const nft = Nft.load(nftAddress) if (!nft) return @@ -105,3 +116,132 @@ export function handleTokenUriUpdate(event: TokenURIUpdate): void { nftUpdate.save() nft.save() } + +// roles +export function handleAddedManager(event: AddedManager): void { + const nft = getNftToken(event.address) + let existingRoles: string[] + if (!nft.managerRole) existingRoles = [] + else existingRoles = nft.managerRole as string[] + if (!existingRoles.includes(event.params.user.toHexString())) + existingRoles.push(event.params.user.toHexString()) + nft.managerRole = existingRoles + nft.save() +} +export function handleRemovedManager(event: RemovedManager): void { + const nft = getNftToken(event.address) + const newList: string[] = [] + let existingRoles: string[] + if (!nft.managerRole) existingRoles = [] + else existingRoles = nft.managerRole as string[] + if (!existingRoles || existingRoles.length < 1) return + while (existingRoles.length > 0) { + const role = existingRoles.shift().toString() + if (!role) break + if (role !== event.params.user.toHexString()) newList.push(role) + } + nft.managerRole = newList + nft.save() +} + +// storeUpdater +export function handleAddedTo725StoreList(event: AddedTo725StoreList): void { + const nft = getNftToken(event.address) + let existingRoles: string[] + if (!nft.storeUpdateRole) existingRoles = [] + else existingRoles = nft.storeUpdateRole as string[] + if (!existingRoles.includes(event.params.user.toHexString())) + existingRoles.push(event.params.user.toHexString()) + nft.storeUpdateRole = existingRoles + nft.save() +} + +export function handleRemovedFrom725StoreList( + event: RemovedFrom725StoreList +): void { + const nft = getNftToken(event.address) + const newList: string[] = [] + let existingRoles: string[] + if (!nft.storeUpdateRole) existingRoles = [] + else existingRoles = nft.storeUpdateRole as string[] + if (!existingRoles || existingRoles.length < 1) return + while (existingRoles.length > 0) { + const role = existingRoles.shift().toString() + if (!role) break + if (role !== event.params.user.toHexString()) newList.push(role) + } + nft.storeUpdateRole = newList + nft.save() +} + +// erc20Deployer +export function handleAddedToCreateERC20List( + event: AddedToCreateERC20List +): void { + const nft = getNftToken(event.address) + let existingRoles: string[] + if (!nft.erc20DeployerRole) existingRoles = [] + else existingRoles = nft.erc20DeployerRole as string[] + if (!existingRoles.includes(event.params.user.toHexString())) + existingRoles.push(event.params.user.toHexString()) + nft.erc20DeployerRole = existingRoles + nft.save() +} + +export function handleRemovedFromCreateERC20List( + event: RemovedFromCreateERC20List +): void { + const nft = getNftToken(event.address) + const newList: string[] = [] + let existingRoles: string[] + if (!nft.erc20DeployerRole) existingRoles = [] + else existingRoles = nft.erc20DeployerRole as string[] + if (!existingRoles || existingRoles.length < 1) return + while (existingRoles.length > 0) { + const role = existingRoles.shift().toString() + if (!role) break + if (role !== event.params.user.toHexString()) newList.push(role) + } + nft.erc20DeployerRole = newList + nft.save() +} + +// metadata updater +export function handleAddedToMetadataList(event: AddedToMetadataList): void { + const nft = getNftToken(event.address) + let existingRoles: string[] + if (!nft.metadataRole) existingRoles = [] + else existingRoles = nft.metadataRole as string[] + if (!existingRoles.includes(event.params.user.toHexString())) + existingRoles.push(event.params.user.toHexString()) + nft.metadataRole = existingRoles + nft.save() +} + +export function handleRemovedFromMetadataList( + event: RemovedFromMetadataList +): void { + const nft = getNftToken(event.address) + const newList: string[] = [] + let existingRoles: string[] + if (!nft.metadataRole) existingRoles = [] + else existingRoles = nft.metadataRole as string[] + if (!existingRoles || existingRoles.length < 1) return + while (existingRoles.length > 0) { + const role = existingRoles.shift().toString() + if (!role) break + if (role !== event.params.user.toHexString()) newList.push(role) + } + nft.metadataRole = newList + nft.save() +} + +export function handleCleanedPermissions(event: CleanedPermissions): void { + const nft = getNftToken(event.address) + const newList: string[] = [] + nft.metadataRole = newList + nft.erc20DeployerRole = newList + nft.storeUpdateRole = newList + nft.managerRole = newList + nft.save() +} diff --git a/src/mappings/pool.ts b/src/mappings/pool.ts index 37001e2..a672824 100644 --- a/src/mappings/pool.ts +++ b/src/mappings/pool.ts @@ -37,7 +37,7 @@ export function handleJoin(event: LOG_JOIN): void { // get token, update pool transaction, poolSnapshot const poolSnapshot = getPoolSnapshot(pool.id, event.block.timestamp.toI32()) - const token = getToken(event.params.tokenIn.toHex()) + const token = getToken(event.params.tokenIn, false) const ammount = weiToDecimal( event.params.tokenAmountIn.toBigDecimal(), token.decimals @@ -76,7 +76,7 @@ export function handleExit(event: LOG_EXIT): void { pool.joinCount = pool.joinCount.plus(integer.ONE) // get token and update pool transaction, value is negative because this is an exit event. - const token = getToken(event.params.tokenOut.toHex()) + const token = getToken(event.params.tokenOut, false) const poolSnapshot = getPoolSnapshot(pool.id, event.block.timestamp.toI32()) const ammount = weiToDecimal( event.params.tokenAmountOut.toBigDecimal(), @@ -116,7 +116,8 @@ export function handleSwap(event: LOG_SWAP): void { const poolSnapshot = getPoolSnapshot(pool.id, event.block.timestamp.toI32()) // get token out and update pool transaction, value is negative - const tokenOut = getToken(event.params.tokenOut.toHex()) + const tokenOut = getToken(event.params.tokenOut, false) + const ammountOut = weiToDecimal( event.params.tokenAmountOut.toBigDecimal(), tokenOut.decimals @@ -143,7 +144,7 @@ export function handleSwap(event: LOG_SWAP): void { } // update pool token in - const tokenIn = getToken(event.params.tokenIn.toHex()) + const tokenIn = getToken(event.params.tokenIn, false) const ammountIn = weiToDecimal( event.params.tokenAmountIn.toBigDecimal(), tokenIn.decimals @@ -190,7 +191,7 @@ export function handleSetup(event: LOG_SETUP): void { const pool = getPool(event.address.toHex()) pool.controller = event.params.caller.toHexString() - const token = getToken(event.params.baseToken.toHex()) + const token = getToken(event.params.baseToken, false) pool.baseToken = token.id pool.baseTokenWeight = weiToDecimal( event.params.baseTokenWeight.toBigDecimal(), @@ -198,7 +199,7 @@ export function handleSetup(event: LOG_SETUP): void { ) // decimals hardcoded because datatokens have 18 decimals - const datatoken = getToken(event.params.datatoken.toHex()) + const datatoken = getToken(event.params.datatoken, true) pool.datatoken = datatoken.id pool.datatokenWeight = weiToDecimal( event.params.datatokenWeight.toBigDecimal(), diff --git a/src/mappings/utils/dispenserUtils.ts b/src/mappings/utils/dispenserUtils.ts index f46b840..733a1f6 100644 --- a/src/mappings/utils/dispenserUtils.ts +++ b/src/mappings/utils/dispenserUtils.ts @@ -1,9 +1,10 @@ import { Dispenser } from '../../@types/schema' import { getToken } from './tokenUtils' +import { Address } from '@graphprotocol/graph-ts' export function createDispenser(address: string): Dispenser { const dispenser = new Dispenser(address) - dispenser.token = getToken(address).id + dispenser.token = getToken(Address.fromString(address), true).id dispenser.save() return dispenser } diff --git a/src/mappings/utils/tokenUtils.ts b/src/mappings/utils/tokenUtils.ts index 8b2f561..d32f2d3 100644 --- a/src/mappings/utils/tokenUtils.ts +++ b/src/mappings/utils/tokenUtils.ts @@ -1,24 +1,52 @@ import { Address, log } from '@graphprotocol/graph-ts' -import { Token } from '../../@types/schema' +import { Nft, Token } from '../../@types/schema' import { ERC20 } from '../../@types/templates/ERC20Template/ERC20' +import { ERC20Template, ERC721Template } from '../../@types/templates' +import { addNft } from './globalUtils' -export function createToken(address: string): Token { - log.debug('started creating token with address: {}', [address]) - const token = new Token(address) - const contract = ERC20.bind(Address.fromString(address)) +export function createToken(address: Address, isDatatoken: boolean): Token { + log.debug('started creating token with address: {}', [address.toHexString()]) + if (isDatatoken) { + ERC20Template.create(address) + } + const token = new Token(address.toHexString()) + const contract = ERC20.bind(address) token.name = contract.name() token.symbol = contract.symbol() - token.address = address - token.isDatatoken = false + token.address = address.toHexString() + token.isDatatoken = isDatatoken token.decimals = contract.decimals() token.save() return token } -export function getToken(address: string): Token { - let newToken = Token.load(address) +export function getToken(address: Address, isDatatoken: boolean): Token { + let newToken = Token.load(address.toHexString()) if (newToken === null) { - newToken = createToken(address) + newToken = createToken(address, isDatatoken) + } + return newToken +} + +export function createNftToken(address: Address): Nft { + log.debug('started creating nft token with address: {}', [ + address.toHexString() + ]) + ERC721Template.create(address) + const token = new Nft(address.toHexString()) + // const contract = ERC721Template.bind(address) + token.name = '' + token.symbol = '' + token.address = address.toHexString() + token.save() + addNft() + return token +} + +export function getNftToken(address: Address): Nft { + let newToken = Nft.load(address.toHexString()) + if (newToken === null) { + newToken = createNftToken(address) } return newToken } diff --git a/subgraph.template.yaml b/subgraph.template.yaml index a60c0c5..0a783a1 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -21,6 +21,8 @@ dataSources: abis: - name: ERC721Factory file: ./node_modules/@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json + - name: ERC20 + file: ./abis/ERC20.json eventHandlers: - event: NFTCreated(indexed address,indexed address,string,address,string,string) handler: handleNftCreated @@ -79,6 +81,8 @@ dataSources: abis: - name: Dispenser file: ./node_modules/@oceanprotocol/contracts/artifacts/contracts/pools/dispenser/Dispenser.sol/Dispenser.json + - name: ERC20 + file: ./abis/ERC20.json eventHandlers: - event: DispenserCreated(indexed address,indexed address,uint256,uint256,address) handler: handleNewDispenser @@ -110,6 +114,8 @@ dataSources: abis: - name: FactoryRouter file: ./node_modules/@oceanprotocol/contracts/artifacts/contracts/pools/FactoryRouter.sol/FactoryRouter.json + - name: ERC20 + file: ./abis/ERC20.json eventHandlers: - event: NewPool(indexed address,bool) handler: handleNewPool @@ -145,6 +151,17 @@ templates: handler: handlePublishMarketFee - event: PublishMarketFeeChanged(address,address,address,uint256) handler: handlePublishMarketFeeChanged + - event: AddedMinter(indexed address,indexed address,uint256,uint256) + handler: handleAddedMinter + - event: AddedPaymentManager(indexed address,indexed address,uint256,uint256) + handler: handleAddedPaymentManager + - event: RemovedMinter(indexed address,indexed address,uint256,uint256) + handler: handleRemovedMinter + - event: RemovedPaymentManager(indexed address,indexed address,uint256,uint256) + handler: handleRemovedPaymentManager + - event: CleanedPermissions(indexed address,uint256,uint256) + handler: handleCleanedPermissions + - name: BPool kind: ethereum/contract network: __NETWORK__ @@ -199,12 +216,32 @@ templates: file: ./node_modules/@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json - name: ERC721RolesAddress file: ./node_modules/@oceanprotocol/contracts/artifacts/contracts/utils/ERC721RolesAddress.sol/ERC721RolesAddress.json + - name: ERC20 + file: ./abis/ERC20.json eventHandlers: - event: MetadataCreated(indexed address,uint8,string,bytes,bytes,bytes32,uint256,uint256) - handler: handleCreated + handler: handleMetadataCreated - event: MetadataUpdated(indexed address,uint8,string,bytes,bytes,bytes32,uint256,uint256) - handler: handleUpdated + handler: handleMetadataUpdated - event: MetadataState(indexed address,uint8,uint256,uint256) - handler: handleState + handler: handleMetadataState - event: TokenURIUpdate(indexed address,string,uint256,uint256,uint256) - handler: handleTokenUriUpdate \ No newline at end of file + handler: handleTokenUriUpdate + - event: AddedManager(indexed address,indexed address,uint256,uint256) + handler: handleAddedManager + - event: AddedTo725StoreList(indexed address,indexed address,uint256,uint256) + handler: handleAddedTo725StoreList + - event: AddedToCreateERC20List(indexed address,indexed address,uint256,uint256) + handler: handleAddedToCreateERC20List + - event: AddedToMetadataList(indexed address,indexed address,uint256,uint256) + handler: handleAddedToMetadataList + - event: RemovedFrom725StoreList(indexed address,indexed address,uint256,uint256) + handler: handleRemovedFrom725StoreList + - event: RemovedFromCreateERC20List(indexed address,indexed address,uint256,uint256) + handler: handleRemovedFromCreateERC20List + - event: RemovedFromMetadataList(indexed address,indexed address,uint256,uint256) + handler: handleRemovedFromMetadataList + - event: RemovedManager(indexed address,indexed address,uint256,uint256) + handler: handleRemovedManager + - event: CleanedPermissions(indexed address,uint256,uint256) + handler: handleCleanedPermissions