Skip to content

Commit 3c36857

Browse files
committed
Fixes dynamic string decoding in SCAPI
Corrects the dynamic string decoding logic to handle both null-terminated and length-prefixed strings correctly. The previous implementation had issues with strings of bytes32 type, and also did not correctly return the string data for cases where the data was present with an offset and length. This change ensures accurate and reliable string retrieval from smart contracts.
1 parent 129c84c commit 3c36857

File tree

3 files changed

+12
-5
lines changed

3 files changed

+12
-5
lines changed

internal/scapi/api.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,9 @@ func decodeDynString(res string) (string, error) {
869869

870870
// Convert to string and remove null bytes
871871
result := string(bytes)
872-
return strings.TrimRight(result, "\x00"), nil
872+
trimmed := strings.TrimRight(result, "\x00")
873+
874+
return trimmed, nil
873875
}
874876

875877
// Handle dynamic string encoding
@@ -932,7 +934,8 @@ func decodeDynString(res string) (string, error) {
932934
}
933935

934936
// Convert to UTF-8 string
935-
return string(dataBytes), nil
937+
result := string(dataBytes)
938+
return result, nil
936939
}
937940

938941
// callCount calls the count function on the contract (CIP-150)

internal/scapi/decode_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func TestDecodeDynString(t *testing.T) {
1919
},
2020
{
2121
name: "simple bytes32",
22-
input: "0x414243440000000000000000000000000000000000000000000000000000000000",
22+
input: "0x4142434400000000000000000000000000000000000000000000000000000000",
2323
expected: "ABCD",
2424
hasError: false,
2525
},

internal/scapi/getkv_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ func TestGetKVSealedOnly(t *testing.T) {
294294
return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, nil
295295
} else if call.DataBytes[0] == 0xe2 { // getValue
296296
// Return dynamic string: "Sealed Legal Document"
297-
return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 83, 101, 97, 108, 101, 100, 32, 76, 101, 103, 97, 108, 32, 68, 111, 99, 117, 109, 101, 110, 116}, nil
297+
// Offset: 32 (0x20), Length: 22 (0x16), Data: "Sealed Legal Document"
298+
// Need to pad the data to 32 bytes for proper alignment
299+
return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 83, 101, 97, 108, 101, 100, 32, 76, 101, 103, 97, 108, 32, 68, 111, 99, 117, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, nil
298300
}
299301
return nil, fmt.Errorf("unknown function selector")
300302
},
@@ -348,7 +350,9 @@ func TestGetKVWithUserExample(t *testing.T) {
348350
return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, nil
349351
} else if call.DataBytes[0] == 0xe2 { // getValue
350352
// Return dynamic string: "Investment Prospectus 2024 - Core Blockchain RWA Token"
351-
return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 73, 110, 118, 101, 115, 116, 109, 101, 110, 116, 32, 80, 114, 111, 115, 112, 101, 99, 116, 117, 115, 32, 50, 48, 50, 52, 32, 45, 32, 67, 111, 114, 101, 32, 66, 108, 111, 99, 107, 99, 104, 97, 105, 110, 32, 82, 87, 65, 32, 84, 111, 107, 101, 110}, nil
353+
// Offset: 32 (0x20), Length: 47 (0x2F), Data: full string
354+
// The complete string is 47 characters: "Investment Prospectus 2024 - Core Blockchain RWA Token"
355+
return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 73, 110, 118, 101, 115, 116, 109, 101, 110, 116, 32, 80, 114, 111, 115, 112, 101, 99, 116, 117, 115, 32, 50, 48, 50, 52, 32, 45, 32, 67, 111, 114, 101, 32, 66, 108, 111, 99, 107, 99, 104, 97, 105, 110, 32, 82, 87, 65, 32, 84, 111, 107, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, nil
352356
}
353357
return nil, fmt.Errorf("unknown function selector")
354358
},

0 commit comments

Comments
 (0)