hiero-ledger / hiero-ledger/hiero-sdk-cpp
[Beginner]: Add `toEvmAddress()` to entity IDs and deprecate `toSolidityAddress()`
- Dominant language
- C++
- Stars
- 42
- Forks
- 108
- Avg merge
- 11h 45m
- Merged PRs (30d)
- 2
Description
### 🐥 Beginner Friendly
This issue is a great fit for contributors who are ready to explore the Hiero C++ codebase a little more and take on slightly more independent work.
Beginner Issues often involve reading existing C++ code, understanding how different parts of the SDK fit together, and making small, thoughtful updates that follow established patterns.
The goal is to support skill growth while keeping the experience approachable, well-scoped, and enjoyable.
> [!IMPORTANT]
> ### 🐥 About Beginner Issues
>
> Beginner Issues are a great next step for contributors who feel comfortable with the basic project workflow and want to explore the codebase a little more.
>
> These issues often involve:
> - Reading existing C++ code
> - Understanding how different parts of the SDK fit together
> - Making small, thoughtful updates that follow established patterns
>
> You'll usually see Beginner Issues focused on things like:
> - Small, well-scoped improvements to existing tests
> - Narrow updates to `src` functionality (e.g. refining helpers or improving readability)
> - Documentation or comment clarity
> - Enhancements to existing examples
>
> Other types of contributions — such as brand-new features, broader system changes, or deeper technical work — are just as valuable and may use different labels.
### 👾 Description of the Task
Four public entity-ID types expose `toSolidityAddress()` for what the ecosystem now consistently calls an **EVM address**:
```
src/sdk/main/include/AccountId.h:177
src/sdk/main/include/ContractId.h:181
src/sdk/main/include/FileId.h:153
src/sdk/main/include/TopicId.h:111
```
"Solidity address" is the legacy name. The Java SDK has already moved in this direction — `toSolidityAddress()` is deprecated there in favor of `toEvmAddress()` — and the C++ SDK should follow so the naming is consistent across SDKs (and with this SDK's own `ECDSAsecp256k1PublicKey::toEvmAddress()` and the `fromEvmAddress()` factories that already exist on `AccountId` and `ContractId`).
This is **not breaking**: `toSolidityAddress()` is retained and deprecated, not removed. The repo already has precedent for exactly this pattern — see `setKey` in [src/sdk/main/include/AccountCreateTransaction.h:91](../../src/sdk/main/include/AccountCreateTransaction.h):
```cpp
[[deprecated("Use setKeyWithoutAlias() instead")]] AccountCreateTransaction& setKey(const std::shared_ptr& key);
```
### 💡 Proposed Solution
For each of the four classes, add `toEvmAddress()` as the preferred name and deprecate the old one. Using `AccountId` as the model:
```cpp
/**
* Get the EVM address representation of this AccountId.
* Preferred replacement for toSolidityAddress().
*
* @return The EVM address representation of this AccountId.
* @throws IllegalStateException If this AccountId contains an alias.
*/
[[nodiscard]] std::string toEvmAddress() const;
/**
* @deprecated Use toEvmAddress() instead.
*/
[[deprecated("Use toEvmAddress() instead")]] [[nodiscard]] std::string toSolidityAddress() const;
```
In each `.cc` file, move the existing body into `toEvmAddress()` and have the deprecated method delegate:
```cpp
std::string AccountId::toSolidityAddress() const
{
return toEvmAddress();
}
```
The return type stays `std::string` so the new method is a drop-in replacement (callers needing an `EvmAddress` object can use `EvmAddress::fromString()`).
Deliverables:
1. `toEvmAddress()` added and `toSolidityAddress()` deprecated on `AccountId`, `ContractId`, `FileId`, and `TopicId`. (`DelegateContractId` inherits from `ContractId` — [DelegateContractId.h:23](../../src/sdk/main/include/DelegateContractId.h) — so it needs no separate change.)
2. All in-repo callers migrated to `toEvmAddress()` so the build stays free of deprecation warnings.
3. Unit tests cover the new methods.
### 👩💻 Implementation Steps
- [ ] Update the four header/source pairs (`AccountId`, `ContractId`, `FileId`, `TopicId`) as shown above. The existing bodies are at [AccountId.cc:228](../../src/sdk/main/src/AccountId.cc), [ContractId.cc:186](../../src/sdk/main/src/ContractId.cc), [FileId.cc:124](../../src/sdk/main/src/FileId.cc), and [TopicId.cc:92](../../src/sdk/main/src/TopicId.cc) — move each body unchanged into `toEvmAddress()`.
- [ ] While moving the bodies, update the two exception messages that say "Solidity address" to say "EVM address" (`AccountId.cc:240`, `ContractId.cc:198-199` — the latter also has a small typo: "a contract number **of** EVM address" should be "a contract number **or** EVM address").
- [ ] Migrate the in-repo call sites to `toEvmAddress()` (otherwise they emit deprecation warnings):
- `src/sdk/main/src/impl/MirrorNodeContractQuery.cc:125`
- `src/sdk/tests/integration/EthereumTransactionIntegrationTests.cc:87`
- `src/sdk/examples/AccountCreationWaysExample.cpp:28`
- `src/sdk/examples/ZeroTokenOperationsExample.cpp:48-49`
- `src/sdk/examples/SolidityPrecompileExample.cpp:42-43`
- [ ] Add unit tests for `toEvmAddress()` in [AccountIdUnitTests.cc](../../src/sdk/tests/unit/AccountIdUnitTests.cc), [ContractIdUnitTests.cc](../../src/sdk/tests/unit/ContractIdUnitTests.cc), [FileIdUnitTests.cc](../../src/sdk/tests/unit/FileIdUnitTests.cc), and [TopicIdUnitTests.cc](../../src/sdk/tests/unit/TopicIdUnitTests.cc). There are currently no unit tests for `toSolidityAddress()` at all, so these are pure additions. Cover at least:
- a numeric ID produces the expected 40-char hex address (e.g. `AccountId(1ULL).toEvmAddress()` ends in `...01`),
- `AccountId` with an EVM-address alias returns the alias hex (`AccountId.cc:230-233` branch),
- `ContractId` constructed from an EVM address returns that address (`ContractId.cc:188-191` branch),
- the no-number/no-alias cases throw `IllegalStateException` where applicable.
- [ ] Build and run the affected unit suites:
```bash
cmake --preset linux-x64-debug -DBUILD_TESTS=ON
cmake --build --preset linux-x64-debug -j 6
ctest -C Debug --test-dir build/linux-x64-debug \
-R "AccountIdUnitTests|ContractIdUnitTests|FileIdUnitTests|TopicIdUnitTests"
```
**Explicitly out of scope** (candidates for follow-up issues — please don't fold them into this PR):
- The `fromSolidityAddress()` factories. `FileId`, `TopicId`, `TokenId`, and `DelegateContractId` have no `fromEvmAddress()` replacement yet, so deprecating the from-direction now would leave users without a path forward.
- The internal helper `internal::EntityIdHelper::toSolidityAddress` ([impl/EntityIdHelper.h:142](../../src/sdk/main/include/impl/EntityIdHelper.h)) — it is not public API, so renaming it is optional cleanup, not part of this issue.
### ✅ Acceptance Criteria
- [ ] **Scope:** Changes are limited to the four entity-ID header/source pairs, the listed call sites, and the four unit-test files.
- [ ] **API:** `toEvmAddress()` exists on `AccountId`, `ContractId`, `FileId`, and `TopicId`; `toSolidityAddress()` is marked `[[deprecated("Use toEvmAddress() instead")]]` and still returns the same value as before (not removed, not breaking).
- [ ] **Behavior:** Address output is byte-for-byte identical to the previous `toSolidityAddress()` output; only the exception-message wording changes.
- [ ] **Warnings:** The SDK, examples, and tests build without deprecation warnings (no remaining in-repo `toSolidityAddress()` callers).
- [ ] **Tests:** New unit tests cover the numeric, alias/EVM-address, and throwing paths; all existing tests still pass.
- [ ] **Review:** All code review feedback addressed.
---
### 📋 Step-by-Step Contribution Guide
To help keep contributions consistent and easy to review, we recommend following these steps:
- [ ] Comment `/assign` to request the issue
- [ ] Wait for assignment
- [ ] Fork the repository and create a branch
- [ ] Set up the project using the instructions in `README.md`
- [ ] Make the requested changes
- [ ] Sign each commit using `-s -S`
- [ ] Push your branch and open a pull request
Read [Workflow Guide](https://github.com/hiero-ledger/hiero-sdk-cpp/blob/main/docs/training/workflow.md) for step-by-step workflow guidance.
Read [README.md](https://github.com/hiero-ledger/hiero-sdk-cpp/blob/main/README.md) for setup instructions.
❗ Pull requests **cannot be merged** without `S` and `s` signed commits.
See the [Signing Guide](https://github.com/hiero-ledger/hiero-sdk-cpp/blob/main/docs/training/signing.md).
### 🤔 Additional Information
If you have questions while working on this issue, feel free to ask!
You can reach the community and maintainers here: [Hiero-SDK-C++ Discord](https://discord.com/channels/905194001349627914/1337424839761465364)
Whether you need help finding the right file, understanding the entity-ID classes, or confirming your approach — we're happy to help.
Contributor guide
Research direction
Start with the existing methods in the AccountId, ContractId, FileId, and TopicId header/source pairs and compare the deprecation precedent in AccountCreateTransaction.h. Search the listed SDK, test, and example call sites, then run the specified CMake build and ctest command. Done means all four public types expose toEvmAddress(), old callers are migrated, deprecation is retained, and the listed unit suites cover the requested paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake, cpp
- Domain
- api, blockchain, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100