diff --git a/CHANGELOG.md b/CHANGELOG.md index 0534e71d7..43b028938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - This applies to `submit`, `signAndSubmit`, `restoreFootprint`, and therefore to `ContractClient.invoke` when it submits. - fix: always encode text as UTF-8 in `Scv.toString(String)`, `Sep10Challenge` (`web_auth_domain` / `client_domain`), `Util.paddedByteArray(String, int)`, and the `SorobanServer` request body. They used the JVM default charset, so non-ASCII text produced different bytes on JVMs where that is not UTF-8. - chore: upgrade generated XDR definitions to Protocol 30. +- fix: `StrKey.decodeClaimableBalance` and `StrKey.isValidClaimableBalance` now reject a claimable balance strkey (`B...`) whose type byte is not 0, as SEP-23 requires; `CLAIMABLE_BALANCE_ID_TYPE_V0` is the only type. Such a key used to be accepted, so `new Address(...)` took it and the error only surfaced in `Address.toSCAddress`. `new Address(...)` now throws `IllegalArgumentException` up front. - refactor: deprecate `GetEventsResponse.EventInfo.inSuccessfulContractCall`. Stellar RPC no longer returns it from `getEvents` ([stellar-rpc#1050](https://github.com/stellar/stellar-rpc/pull/1050)), so it is `null` with newer servers. It will be removed in the next major release. ## 5.0.0 diff --git a/src/main/java/org/stellar/sdk/StrKey.java b/src/main/java/org/stellar/sdk/StrKey.java index b6ed2a625..1e97dfd91 100644 --- a/src/main/java/org/stellar/sdk/StrKey.java +++ b/src/main/java/org/stellar/sdk/StrKey.java @@ -454,6 +454,13 @@ static byte[] decodeCheck(VersionByte versionByte, char[] encoded) { throw new IllegalArgumentException( "Invalid data length, expected 33 bytes, got " + data.length); } + // SEP-23: the first byte is the claimable balance type, and CLAIMABLE_BALANCE_ID_TYPE_V0 + // is the only one. + if (data[0] != 0) { + throw new IllegalArgumentException( + "Invalid claimable balance type, expected 0 (CLAIMABLE_BALANCE_ID_TYPE_V0), got " + + data[0]); + } break; default: if (data.length != 32) { diff --git a/src/test/kotlin/org/stellar/sdk/AddressTest.kt b/src/test/kotlin/org/stellar/sdk/AddressTest.kt index c68acadf9..c2bacb866 100644 --- a/src/test/kotlin/org/stellar/sdk/AddressTest.kt +++ b/src/test/kotlin/org/stellar/sdk/AddressTest.kt @@ -50,6 +50,14 @@ class AddressTest : address.addressType shouldBe Address.AddressType.LIQUIDITY_POOL } + test("should throw exception for claimable balance ID with a non-zero type") { + val exception = + shouldThrow { + Address("BAAT6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGXACA") + } + exception.message shouldBe "Unsupported address type" + } + test("should throw exception for invalid address") { val exception = shouldThrow { Address(invalidAddress) } exception.message shouldBe "Unsupported address type" diff --git a/src/test/kotlin/org/stellar/sdk/StrKeyTest.kt b/src/test/kotlin/org/stellar/sdk/StrKeyTest.kt index e8e303c30..b7b34ba47 100644 --- a/src/test/kotlin/org/stellar/sdk/StrKeyTest.kt +++ b/src/test/kotlin/org/stellar/sdk/StrKeyTest.kt @@ -191,6 +191,21 @@ class StrKeyTest : StrKey.isValidClaimableBalance( "BAT7RRVQBTQ3TEDLDICV7GNX6GE3KVQFJCNOESUI4QNA4TYYR44P2FS5PZYQ" ) shouldBe false + // SEP-23: invalid claimable balance type (first byte of binary key is not 0) + StrKey.isValidClaimableBalance( + "BAAT6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGXACA" + ) shouldBe false + } + + test("decode rejects a non-zero claimable balance type") { + val exception = + shouldThrow { + StrKey.decodeClaimableBalance( + "BAAT6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGXACA" + ) + } + exception.message shouldBe + "Invalid claimable balance type, expected 0 (CLAIMABLE_BALANCE_ID_TYPE_V0), got 1" } } @@ -355,9 +370,8 @@ class StrKeyTest : "PA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAOQCAQDAQCQMBYIBEFAWDANBYHRAEISCMKBKFQXDAMRUGY4Z2PQ", "PA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAOQCAQDAQCQMBYIBEFAWDANBYHRAEISCMKBKFQXDAMRUGY4DXFH6", "BAAD6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGR4TV", - // We should consider this valid - // Invalid claimablebalance type (first byte of binary key is not 0), - // "BAAT6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGXACA" + // Invalid claimable balance type (first byte of binary key is not 0) + "BAAT6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGXACA", "", ) { key -> shouldThrow { StrKey.decodeEd25519PublicKey(key) }