From d98f59643b4f8d24d3494e759dd602bfb07e6679 Mon Sep 17 00:00:00 2001 From: Michael LeSane Date: Wed, 20 Apr 2022 10:31:51 -0500 Subject: [PATCH 1/4] Integrate parsing and entity logic for contracts and events --- schema.graphql | 41 +++++++ src/mappings/gns.ts | 15 ++- src/mappings/helpers.ts | 24 ++++ src/mappings/metadataHelpers.template.ts | 142 ++++++++++++++++++++++- 4 files changed, 217 insertions(+), 5 deletions(-) diff --git a/schema.graphql b/schema.graphql index 15338313..662abcb8 100644 --- a/schema.graphql +++ b/schema.graphql @@ -522,6 +522,9 @@ type SubgraphDeployment @entity { activeSubgraphCount: Int! "Amount of Subgraph entities that were currently using this deployment when they got deprecated" deprecatedSubgraphCount: Int! + + "The contract sources in this subgraph deployment's manifest" + contracts: [Contract!]! } # TODO - add when we have the ability to parse data sources @@ -1219,6 +1222,32 @@ enum Revocability { Disabled } +""" +Events from contract sources in subgraph manifests +""" +type ContractEvent @entity { + "Address-Event" + id: ID! + "Event" + event: String + "The contract this event is associated with" + contract: Contract! +} + +""" +Contracts in subgraph manifests +""" +type Contract @entity { + "Contract Address" + id: ID! + "Placeholder for contract name, if it can be determined" + name: String + "Subgraph deployments which include this contract in their manifests" + subgraphDeployments: [SubgraphDeployment!]! @derivedFrom(field: "contracts") + "Events associated with this contract" + contractEvents: [ContractEvent!]! @derivedFrom(field: "contract") +} + """ Full test search for displayName and description on the Subgraph Entity """ @@ -1241,3 +1270,15 @@ type _Schema_ algorithm: rank include: [{ entity: "Delegator", fields: [{ name: "defaultDisplayName" }, { name: "id" }] }] ) + @fulltext( + name: "contractEventSearch" + language: en + algorithm: rank + include: [{ entity: "ContractEvent", fields: [{ name: "event" }] }] + ) + @fulltext( + name: "contractSearch" + language: en + algorithm: rank + include: [{ entity: "Contract", fields: [{ name: "id" }] }] + ) diff --git a/src/mappings/gns.ts b/src/mappings/gns.ts index 303c0c59..4fcd4804 100644 --- a/src/mappings/gns.ts +++ b/src/mappings/gns.ts @@ -54,9 +54,9 @@ import { convertBigIntSubgraphIDToBase58, duplicateOrUpdateSubgraphWithNewID, duplicateOrUpdateSubgraphVersionWithNewID, - duplicateOrUpdateNameSignalWithNewID, + duplicateOrUpdateNameSignalWithNewID } from './helpers' -import { fetchSubgraphMetadata, fetchSubgraphVersionMetadata } from './metadataHelpers' +import { fetchSubgraphMetadata, fetchSubgraphVersionMetadata, processManifestForContracts } from './metadataHelpers' export function handleSetDefaultName(event: SetDefaultName): void { let graphAccount = createOrLoadGraphAccount(event.params.graphAccount, event.block.timestamp) @@ -250,7 +250,10 @@ export function handleSubgraphPublished(event: SubgraphPublished): void { // Create subgraph deployment, if needed. Can happen if the deployment has never been staked on let subgraphDeploymentID = event.params.subgraphDeploymentID.toHexString() let deployment = createOrLoadSubgraphDeployment(subgraphDeploymentID, event.block.timestamp) - + + //Associate Contracts and Events with Deployment + processManifestForContracts(subgraph,deployment) + // Create subgraph version let subgraphVersion = new SubgraphVersion(versionIDNew) subgraphVersion.entityVersion = 2 @@ -765,6 +768,9 @@ export function handleSubgraphPublishedV2(event: SubgraphPublished1): void { // Create subgraph deployment, if needed. Can happen if the deployment has never been staked on let subgraphDeploymentID = event.params.subgraphDeploymentID.toHexString() let deployment = createOrLoadSubgraphDeployment(subgraphDeploymentID, event.block.timestamp) + + //Associate Contracts and Events with Deployment + processManifestForContracts(subgraph,deployment) // Create subgraph version let subgraphVersion = new SubgraphVersion(versionID) @@ -774,6 +780,7 @@ export function handleSubgraphPublishedV2(event: SubgraphPublished1): void { subgraphVersion.version = versionNumber.toI32() subgraphVersion.createdAt = event.block.timestamp.toI32() subgraphVersion.save() + let oldDeployment: SubgraphDeployment | null = null if (oldVersionID != null) { @@ -1277,6 +1284,8 @@ export function handleSubgraphVersionUpdated(event: SubgraphVersionUpdated): voi // Create subgraph deployment, if needed. Can happen if the deployment has never been staked on let subgraphDeploymentID = event.params.subgraphDeploymentID.toHexString() let deployment = createOrLoadSubgraphDeployment(subgraphDeploymentID, event.block.timestamp) + //Associate Contracts and Events with Deployment + processManifestForContracts(subgraph,deployment) // Create subgraph version let subgraphVersion = new SubgraphVersion(versionID) diff --git a/src/mappings/helpers.ts b/src/mappings/helpers.ts index f7bfcc9b..1ac5f1de 100644 --- a/src/mappings/helpers.ts +++ b/src/mappings/helpers.ts @@ -19,6 +19,8 @@ import { SubgraphCategoryRelation, NameSignalSubgraphRelation, CurrentSubgraphDeploymentRelation, + Contract, + ContractEvent } from '../types/schema' import { ENS } from '../types/GNS/ENS' import { Controller } from '../types/Controller/Controller' @@ -538,6 +540,28 @@ export function createOrLoadGraphNetwork( return graphNetwork as GraphNetwork } +export function createOrLoadContract(contractID: String): Contract { + let contract = Contract.load(contractID) + if(contract == null) { + contract = new Contract(contractID) + contract.save() + } + return contract as Contract +} + +export function createOrLoadContractEvent(contractID: String,event: String): ContractEvent { +// TODO This could really benefit from the use of name mangling, if possible. There might be contract event redundancies without it. + let contractEvent = ContractEvent.load(joinID([contractID,event])) + if(contractEvent == null) { + contractEvent = new ContractEvent(joinID([contractID,event])) + } + contractEvent.contract = contractID + contractEvent.event = event + contractEvent.save() + return contractEvent as ContractEvent +} + + export function addQm(a: ByteArray): ByteArray { let out = new Uint8Array(34) out[0] = 0x12 diff --git a/src/mappings/metadataHelpers.template.ts b/src/mappings/metadataHelpers.template.ts index 9864d91c..ba968b3a 100644 --- a/src/mappings/metadataHelpers.template.ts +++ b/src/mappings/metadataHelpers.template.ts @@ -1,7 +1,7 @@ import { json, ipfs, Bytes, JSONValueKind, log } from '@graphprotocol/graph-ts' -import { GraphAccount, Subgraph, SubgraphVersion, SubgraphDeployment } from '../types/schema' +import { GraphAccount, Subgraph, SubgraphVersion, SubgraphDeployment, Contract, ContractEvent } from '../types/schema' import { jsonToString } from './utils' -import { createOrLoadSubgraphCategory, createOrLoadSubgraphCategoryRelation, createOrLoadNetwork } from './helpers' +import { createOrLoadSubgraphCategory, createOrLoadSubgraphCategoryRelation, createOrLoadNetwork, createOrLoadContract, createOrLoadContractEvent } from './helpers' export function fetchGraphAccountMetadata(graphAccount: GraphAccount, ipfsHash: string): void { {{#ipfs}} @@ -122,3 +122,141 @@ export function fetchSubgraphDeploymentManifest(deployment: SubgraphDeployment, {{/ipfs}} return deployment as SubgraphDeployment } + +/* Subgraph Contract Metadata Extraction & Helpers */ + +export function stripQuotes(str: String): String { + let res = '' + let remove = ['\'','"',' '] + for(let i = 0; i < str.length; i++) { + if(!remove.includes(str[i])) res = res.concat(str[i]) + } + return res as String +} + +export function formatEvent(str: String): String { + let res = '' + let pass = '' + // Strip Quotes - TODO breakout into function common to stripQuotes() + let remove = ['\'','"'] + for(let i = 0; i < str.length; i++) { + if(!remove.includes(str[i])) pass = pass.concat(str[i]) + } + // Newline handling + pass = pass.replaceAll('\r',' ') + pass = pass.replaceAll('\n',' ') + pass = pass.replaceAll('>-',' ') + // Space handling + let last = ' ' + for(let i = 0; i < pass.length; i++) { + if(pass[i] == ' ' && last == ' ') { + continue + } else { + res = res.concat(pass[i]) + } + last = pass[i] + } + res = res.trim() + return res as String +} + +export function extractContractEvents(kind: String, contract: Contract): void { + let eventHandlersSplit = kind.split("eventHandlers:",2) + let eventHandlersStr = '' + if(eventHandlersSplit.length >= 2) { + eventHandlersStr = eventHandlersSplit[1] + } + let eventSplit = eventHandlersStr.split("- event:") + for(let i = 1; i < eventSplit.length; i++) { + let sanitizeSplit = eventSplit[i].split("handler:",2) + let eventIso = formatEvent(sanitizeSplit[0]) + log.debug("Contract event extracted: '{}'",[eventIso]) + let contractEvent = createOrLoadContractEvent(contract.id,eventIso) + } +} + +export function extractContractAddresses(ipfsData: String): Array { + let res = new Array(0) + // Use split() until a suitable YAML parser is found. Approach was used in graph-network-subgraph. + let dataSourcesSplit = ipfsData.split('dataSources:\n',2) + let dataSourcesStr = '' + if(dataSourcesSplit.length >= 2) { + dataSourcesStr = dataSourcesSplit[1]; + } else { + // Problem + return res as Array + } + // Determine where 'dataSources:' ends, exclude everything thereafter. + let sanitizeSplit = dataSourcesStr.split('\n') + let shouldDelete = false + // Assumes 32 for space. + dataSourcesStr = '' + for(let i = 0; i < sanitizeSplit.length; i++) { + if(sanitizeSplit[i].charAt(0) != ' ' || shouldDelete) { + shouldDelete = true + } else { + dataSourcesStr = dataSourcesStr.concat(sanitizeSplit[i]) + if(i < sanitizeSplit.length - 1) { + dataSourcesStr = dataSourcesStr.concat('\n') + } + } + } + // Extract + let kindSplit = dataSourcesStr.split('- kind:') + let sourceStr = '' + let addressStr = '' + let addressIso = '' + for(let i = 1; i < kindSplit.length; i++) { + addressIso = '' + // Source Address + let sourceSplit = kindSplit[i].split(' source:',2) + if(sourceSplit.length < 2) continue + else sourceStr = sourceSplit[1] + + let addressSplit = sourceStr.split(' address:',2) + if(addressSplit.length < 2) continue + else addressStr = addressSplit[1] + + let addressStrSplit = addressStr.split('\n',2) + if(addressStrSplit.length < 2) continue + else addressIso = addressStrSplit[0] + + log.debug("Contract address '{}' extracted",[addressIso]) + res.push(stripQuotes(addressIso)) + + // Isolate contract events + let contract = createOrLoadContract(stripQuotes(addressIso)) + extractContractEvents(kindSplit[i],contract) + } + + return res as Array +} + +export function processManifestForContracts(subgraph: Subgraph, deployment: SubgraphDeployment): void { + {{#ipfs}} + let subgraphDeploymentID = deployment.id + let subgraphID = subgraph.id + let prefix = '1220' + let ipfsHash = Bytes.fromHexString(prefix.concat(subgraphDeploymentID.slice(2))).toBase58() + + log.debug("Checking IPFS for hash '{}'",[ipfsHash]) + + let ipfsData = ipfs.cat(ipfsHash) + + if(ipfsData !== null) { + let contractAddresses = extractContractAddresses(ipfsData.toString()) + let address = '' + for(let i = 0; i < contractAddresses.length; i++) { + address = contractAddresses[i] + log.debug("Associating address '{}'",[address]) + let contract = createOrLoadContract(address) + let assoc = deployment.contracts + if(assoc.indexOf(address) == -1) { + assoc.push(address) + deployment.contracts = assoc + deployment.save() + } + } + } + {{/ipfs}} +} From 773b2a9bfb7dbcbe28cfd0f60ef0d14728746ba4 Mon Sep 17 00:00:00 2001 From: Michael LeSane Date: Sat, 30 Apr 2022 03:00:55 -0500 Subject: [PATCH 2/4] Add SubgraphDeploymentContract relational entity --- schema.graphql | 13 +++++++++-- src/mappings/gns.ts | 10 +------- src/mappings/helpers.ts | 24 ++++++++++++++++++-- src/mappings/metadataHelpers.template.ts | 29 ++++++------------------ 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/schema.graphql b/schema.graphql index 662abcb8..969c2eea 100644 --- a/schema.graphql +++ b/schema.graphql @@ -524,7 +524,7 @@ type SubgraphDeployment @entity { deprecatedSubgraphCount: Int! "The contract sources in this subgraph deployment's manifest" - contracts: [Contract!]! + contracts: [SubgraphDeploymentContract!]! @derivedFrom(field:"subgraphDeployment") } # TODO - add when we have the ability to parse data sources @@ -1243,11 +1243,20 @@ type Contract @entity { "Placeholder for contract name, if it can be determined" name: String "Subgraph deployments which include this contract in their manifests" - subgraphDeployments: [SubgraphDeployment!]! @derivedFrom(field: "contracts") + subgraphDeployments: [SubgraphDeploymentContract!]! @derivedFrom(field:"contract") "Events associated with this contract" contractEvents: [ContractEvent!]! @derivedFrom(field: "contract") } +""" +Deployment-to-Contract relational entity +""" +type SubgraphDeploymentContract @entity { + id: ID! # Concat: Deployment ID, Contract Address + subgraphDeployment: SubgraphDeployment! + contract: Contract! +} + """ Full test search for displayName and description on the Subgraph Entity """ diff --git a/src/mappings/gns.ts b/src/mappings/gns.ts index 4fcd4804..bd6b6f63 100644 --- a/src/mappings/gns.ts +++ b/src/mappings/gns.ts @@ -56,7 +56,7 @@ import { duplicateOrUpdateSubgraphVersionWithNewID, duplicateOrUpdateNameSignalWithNewID } from './helpers' -import { fetchSubgraphMetadata, fetchSubgraphVersionMetadata, processManifestForContracts } from './metadataHelpers' +import { fetchSubgraphMetadata, fetchSubgraphVersionMetadata } from './metadataHelpers' export function handleSetDefaultName(event: SetDefaultName): void { let graphAccount = createOrLoadGraphAccount(event.params.graphAccount, event.block.timestamp) @@ -251,9 +251,6 @@ export function handleSubgraphPublished(event: SubgraphPublished): void { let subgraphDeploymentID = event.params.subgraphDeploymentID.toHexString() let deployment = createOrLoadSubgraphDeployment(subgraphDeploymentID, event.block.timestamp) - //Associate Contracts and Events with Deployment - processManifestForContracts(subgraph,deployment) - // Create subgraph version let subgraphVersion = new SubgraphVersion(versionIDNew) subgraphVersion.entityVersion = 2 @@ -769,9 +766,6 @@ export function handleSubgraphPublishedV2(event: SubgraphPublished1): void { let subgraphDeploymentID = event.params.subgraphDeploymentID.toHexString() let deployment = createOrLoadSubgraphDeployment(subgraphDeploymentID, event.block.timestamp) - //Associate Contracts and Events with Deployment - processManifestForContracts(subgraph,deployment) - // Create subgraph version let subgraphVersion = new SubgraphVersion(versionID) subgraphVersion.entityVersion = 2 @@ -1284,8 +1278,6 @@ export function handleSubgraphVersionUpdated(event: SubgraphVersionUpdated): voi // Create subgraph deployment, if needed. Can happen if the deployment has never been staked on let subgraphDeploymentID = event.params.subgraphDeploymentID.toHexString() let deployment = createOrLoadSubgraphDeployment(subgraphDeploymentID, event.block.timestamp) - //Associate Contracts and Events with Deployment - processManifestForContracts(subgraph,deployment) // Create subgraph version let subgraphVersion = new SubgraphVersion(versionID) diff --git a/src/mappings/helpers.ts b/src/mappings/helpers.ts index 1ac5f1de..b52e104d 100644 --- a/src/mappings/helpers.ts +++ b/src/mappings/helpers.ts @@ -20,11 +20,12 @@ import { NameSignalSubgraphRelation, CurrentSubgraphDeploymentRelation, Contract, - ContractEvent + ContractEvent, + SubgraphDeploymentContract } from '../types/schema' import { ENS } from '../types/GNS/ENS' import { Controller } from '../types/Controller/Controller' -import { fetchSubgraphDeploymentManifest } from './metadataHelpers' +import { fetchSubgraphDeploymentManifest, processManifestForContracts } from './metadataHelpers' import { addresses } from '../../config/addresses' export function createOrLoadSubgraph( @@ -82,6 +83,10 @@ export function createOrLoadSubgraphDeployment( deployment as SubgraphDeployment, deployment.ipfsHash, ) + + //Associate Contracts and Events with Deployment + processManifestForContracts(deployment) + deployment.createdAt = timestamp.toI32() deployment.stakedTokens = BigInt.fromI32(0) deployment.indexingRewardAmount = BigInt.fromI32(0) @@ -540,6 +545,21 @@ export function createOrLoadGraphNetwork( return graphNetwork as GraphNetwork } +export function createOrLoadSubgraphDeploymentContract( + deployment: SubgraphDeployment, + contract: Contract +): SubgraphDeploymentContract { + let assocID = joinID([deployment.id,contract.id]) + let assoc = SubgraphDeploymentContract.load(assocID) + if (assoc == null) { + assoc = new SubgraphDeploymentContract(assocID) + assoc.subgraphDeployment = deployment.id + assoc.contract = contract.id + assoc.save() + } + return assoc as SubgraphDeploymentContract +} + export function createOrLoadContract(contractID: String): Contract { let contract = Contract.load(contractID) if(contract == null) { diff --git a/src/mappings/metadataHelpers.template.ts b/src/mappings/metadataHelpers.template.ts index ba968b3a..91f6ce07 100644 --- a/src/mappings/metadataHelpers.template.ts +++ b/src/mappings/metadataHelpers.template.ts @@ -1,7 +1,7 @@ import { json, ipfs, Bytes, JSONValueKind, log } from '@graphprotocol/graph-ts' -import { GraphAccount, Subgraph, SubgraphVersion, SubgraphDeployment, Contract, ContractEvent } from '../types/schema' +import { GraphAccount, Subgraph, SubgraphVersion, SubgraphDeployment, Contract, ContractEvent, SubgraphDeploymentContract } from '../types/schema' import { jsonToString } from './utils' -import { createOrLoadSubgraphCategory, createOrLoadSubgraphCategoryRelation, createOrLoadNetwork, createOrLoadContract, createOrLoadContractEvent } from './helpers' +import { createOrLoadSubgraphCategory, createOrLoadSubgraphCategoryRelation, createOrLoadNetwork, createOrLoadContract, createOrLoadContractEvent, createOrLoadSubgraphDeploymentContract } from './helpers' export function fetchGraphAccountMetadata(graphAccount: GraphAccount, ipfsHash: string): void { {{#ipfs}} @@ -232,31 +232,16 @@ export function extractContractAddresses(ipfsData: String): Array { return res as Array } -export function processManifestForContracts(subgraph: Subgraph, deployment: SubgraphDeployment): void { - {{#ipfs}} - let subgraphDeploymentID = deployment.id - let subgraphID = subgraph.id - let prefix = '1220' - let ipfsHash = Bytes.fromHexString(prefix.concat(subgraphDeploymentID.slice(2))).toBase58() - - log.debug("Checking IPFS for hash '{}'",[ipfsHash]) - - let ipfsData = ipfs.cat(ipfsHash) - - if(ipfsData !== null) { - let contractAddresses = extractContractAddresses(ipfsData.toString()) +export function processManifestForContracts(deployment: SubgraphDeployment): void { + let manifest = deployment.manifest + if(manifest !== null) { + let contractAddresses = extractContractAddresses(manifest) let address = '' for(let i = 0; i < contractAddresses.length; i++) { address = contractAddresses[i] log.debug("Associating address '{}'",[address]) let contract = createOrLoadContract(address) - let assoc = deployment.contracts - if(assoc.indexOf(address) == -1) { - assoc.push(address) - deployment.contracts = assoc - deployment.save() - } + let assoc = createOrLoadSubgraphDeploymentContract(deployment,contract) } } - {{/ipfs}} } From ea3919b4e0bc66b9aa7083fb63e60091f3db500f Mon Sep 17 00:00:00 2001 From: Michael LeSane Date: Sun, 8 May 2022 17:34:10 -0500 Subject: [PATCH 3/4] add helper function to standardize format of contract addresses --- src/mappings/helpers.ts | 7 +++++++ src/mappings/metadataHelpers.template.ts | 6 +++--- subgraph.template.yaml | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/mappings/helpers.ts b/src/mappings/helpers.ts index b52e104d..a158aba7 100644 --- a/src/mappings/helpers.ts +++ b/src/mappings/helpers.ts @@ -560,6 +560,13 @@ export function createOrLoadSubgraphDeploymentContract( return assoc as SubgraphDeploymentContract } +export function standardizeAddress(address:String): String { + if(address.length == 40) { + address = '0x' + address + } + return address.toLowerCase() as String +} + export function createOrLoadContract(contractID: String): Contract { let contract = Contract.load(contractID) if(contract == null) { diff --git a/src/mappings/metadataHelpers.template.ts b/src/mappings/metadataHelpers.template.ts index a8e92557..925a0779 100644 --- a/src/mappings/metadataHelpers.template.ts +++ b/src/mappings/metadataHelpers.template.ts @@ -1,7 +1,7 @@ import { json, ipfs, Bytes, JSONValueKind, log } from '@graphprotocol/graph-ts' import { GraphAccount, Subgraph, SubgraphVersion, SubgraphDeployment, Contract, ContractEvent, SubgraphDeploymentContract } from '../types/schema' import { jsonToString } from './utils' -import { createOrLoadSubgraphCategory, createOrLoadSubgraphCategoryRelation, createOrLoadNetwork, createOrLoadContract, createOrLoadContractEvent, createOrLoadSubgraphDeploymentContract } from './helpers' +import { createOrLoadSubgraphCategory, createOrLoadSubgraphCategoryRelation, createOrLoadNetwork, createOrLoadContract, createOrLoadContractEvent, createOrLoadSubgraphDeploymentContract, standardizeAddress } from './helpers' export function fetchGraphAccountMetadata(graphAccount: GraphAccount, ipfsHash: string): void { {{#ipfs}} @@ -226,10 +226,10 @@ export function extractContractAddresses(ipfsData: String): Array { else addressIso = addressStrSplit[0] log.debug("Contract address '{}' extracted",[addressIso]) - res.push(stripQuotes(addressIso)) + res.push(standardizeAddress(stripQuotes(addressIso))) // Isolate contract events - let contract = createOrLoadContract(stripQuotes(addressIso)) + let contract = createOrLoadContract(standardizeAddress(stripQuotes(addressIso))) extractContractEvents(kindSplit[i],contract) } diff --git a/subgraph.template.yaml b/subgraph.template.yaml index c8364fc8..632385fe 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -48,6 +48,9 @@ dataSources: - Subgraph - SubgraphVersion - SubgraphDeployment + - SubgraphDeploymentContract + - Contract + - ContractEvent - GraphAccount - NameSignal abis: From c724d75d8c26e717cd883679fa0d2535a088535e Mon Sep 17 00:00:00 2001 From: Michael LeSane Date: Sat, 6 Aug 2022 11:16:45 -0500 Subject: [PATCH 4/4] Add unit test for standardizeAddresses --- tests/metadata.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/metadata.test.ts diff --git a/tests/metadata.test.ts b/tests/metadata.test.ts new file mode 100644 index 00000000..6af08e47 --- /dev/null +++ b/tests/metadata.test.ts @@ -0,0 +1,18 @@ +import { assert, test } from "matchstick-as/assembly/index" +import { Address, BigInt, DataSourceContext, store, Value, Bytes, log, ethereum } from "@graphprotocol/graph-ts" +import { standardizeAddress } from '../src/mappings/helpers' + +test("testStandardizeAddresses", () => { + let addresses = [ + "f55041e37e12cd407ad00ce2910b8269b01263b9", + "F55041E37E12cD407ad00CE2910B8269B01263b9", + "0xf55041e37e12cd407ad00ce2910b8269b01263b9", + "0xF55041E37E12cD407ad00CE2910B8269B01263b9", + ] + + addresses.forEach(function(x) { + let stdAddr = standardizeAddress(x); + let refAddr = "0xf55041e37e12cd407ad00ce2910b8269b01263b9"; + assert.equals(ethereum.Value.fromString(stdAddr),ethereum.Value.fromString(refAddr)); + }); +})