From 3acb73ebe7cf88d7d498820d5c99318b2ad484b2 Mon Sep 17 00:00:00 2001 From: ryley-o <30364988+ryley-o@users.noreply.github.com> Date: Tue, 6 Sep 2022 17:33:43 -0700 Subject: [PATCH 1/4] update test to fail with specific input --- tests/subgraph/minter-suite/minter-suite-mapping.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/subgraph/minter-suite/minter-suite-mapping.test.ts b/tests/subgraph/minter-suite/minter-suite-mapping.test.ts index 2cb5d3ea..3cc6ac47 100644 --- a/tests/subgraph/minter-suite/minter-suite-mapping.test.ts +++ b/tests/subgraph/minter-suite/minter-suite-mapping.test.ts @@ -1620,7 +1620,11 @@ test("handleSetValue should set all values to a designated key in extraMinterDet // If the bytes are not intended to be a human readable string // we should instead convert to their hex string representation - const eventValue = randomAddressGenerator.generateRandomAddress(); + // Always use the following hex string because valid WTF-8 but not valid + // UTF-8, which is a somewhat common edge-case when dealing with bytes + let eventValue = Bytes.fromHexString( + "0x57e32bd396b7c3337dd6b4a672e6d99b47865e56" + ); const configValueSetEvent4: ConfigValueSetBytes = changetype< ConfigValueSetBytes >(newMockEvent()); From a2449fe8012f87677a05ebc5b5e1b649d4cd8ad9 Mon Sep 17 00:00:00 2001 From: ryley-o <30364988+ryley-o@users.noreply.github.com> Date: Tue, 6 Sep 2022 19:44:59 -0700 Subject: [PATCH 2/4] bug fix bytesToJSONValue string encoding logic --- src/helpers.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index ad342079..f31e26ec 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -177,10 +177,21 @@ export function arrayToJSONValue(value: string): JSONValue { // If byte data is parseable to a valid unicode string then do so // otherwise parse the byte data to a hex string export function bytesToJSONValue(value: Bytes): JSONValue { - // If the bytes cannot be - let result = json.try_fromString('["' + value.toString() + '"]'); - if (result.isError) { - result = json.try_fromString('["' + value.toHexString() + '"]'); + // fallback - assume the data is a hex string (always valid) + let result = json.try_fromString('["' + value.toHexString() + '"]'); + // If the bytes can be parsed as a string, then losslessly re-encoded into + // UTF-8 bytes, then consider a valid UTF-8 encoded string and store + // string value in json. + // note: Bytes.toString() uses WTF-8 encoding as opposed to UTF-8. Solidity + // encodes UTF-8 strings, so safe assume any string data are UTF-8 encoded. + let stringValue: string = value.toString(); + let reEncodedBytesValue: Bytes = Bytes.fromUTF8(stringValue); + if (reEncodedBytesValue.toHexString() == value.toHexString()) { + // if the bytes are the same then the string was valid UTF-8 + let potentialResult = json.try_fromString('["' + stringValue + '"]'); + if (potentialResult.isOk) { + result = potentialResult; + } } return result.value.toArray()[0]; } From f60b776ace7e1d6666e6fba4ebc313007a0f06ef Mon Sep 17 00:00:00 2001 From: ryley-o <30364988+ryley-o@users.noreply.github.com> Date: Wed, 7 Sep 2022 12:17:14 -0700 Subject: [PATCH 3/4] add edge-case to handleAddManyBytesValue test to expose bug --- .../minter-suite/minter-suite-mapping.test.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/subgraph/minter-suite/minter-suite-mapping.test.ts b/tests/subgraph/minter-suite/minter-suite-mapping.test.ts index 3cc6ac47..7503858b 100644 --- a/tests/subgraph/minter-suite/minter-suite-mapping.test.ts +++ b/tests/subgraph/minter-suite/minter-suite-mapping.test.ts @@ -1824,13 +1824,36 @@ test("handleAddManyBytesValue should add a value to an array at a designated key '{"array":["im bytes"]}' ); - handleAddManyBytesValue(configValueSetEvent); + // add another value, this time with bytes that should format to hex string + const configValueSetEvent2: ConfigValueAddedToSetBytes = changetype< + ConfigValueAddedToSetBytes + >(newMockEvent()); + // Always use the following hex string because valid WTF-8 but not valid + // UTF-8, which is a somewhat common edge-case when dealing with bytes + let eventValue = Bytes.fromHexString( + "0x57e32bd396b7c3337dd6b4a672e6d99b47865e56" + ); + configValueSetEvent2.address = minterAddress; + configValueSetEvent2.parameters = [ + new ethereum.EventParam( + "_projectId", + ethereum.Value.fromUnsignedBigInt(projectId) + ), + new ethereum.EventParam( + "_key", + ethereum.Value.fromBytes(Bytes.fromUTF8("array")) + ), + new ethereum.EventParam("_value", ethereum.Value.fromBytes(eventValue)) + ]; + configValueSetEvent2.block.timestamp = CURRENT_BLOCK_TIMESTAMP; + + handleAddManyBytesValue(configValueSetEvent2); assert.fieldEquals( PROJECT_MINTER_CONFIGURATION_ENTITY_TYPE, getProjectMinterConfigId(minterAddress.toHexString(), project.id), "extraMinterDetails", - '{"array":["im bytes","im bytes"]}' + '{"array":["im bytes","0x57e32bd396b7c3337dd6b4a672e6d99b47865e56"]}' ); }); test("handleRemoveValue should remove the key/value from extraMinterDetails", () => { From aade9883f241cc07293479639c370f647b9fe5ff Mon Sep 17 00:00:00 2001 From: ryley-o <30364988+ryley-o@users.noreply.github.com> Date: Wed, 7 Sep 2022 12:24:29 -0700 Subject: [PATCH 4/4] bug fix when adding bytes to set --- src/minter-suite-mapping.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/minter-suite-mapping.ts b/src/minter-suite-mapping.ts index 75bb58d5..8c110c92 100644 --- a/src/minter-suite-mapping.ts +++ b/src/minter-suite-mapping.ts @@ -727,7 +727,8 @@ export function handleAddManyValueGeneric( ) { stringVal = event.params._value.toHexString(); } else { - stringVal = event.params._value.toString(); + // for Bytes, use method to determine if string or hexString + stringVal = bytesToJSONValue(event.params._value).toString(); } arr.push(stringToJSONString(stringVal)); newValue = arrayToJSONValue(arr.toString());