Skip to content

🟠 scValToString renders contract addresses as raw hex, not StrKey — per-token history and explorer links are broken #1015

Description

@Ejirowebfi

Severity: High · Area: Frontend (frontend/src/services/stellar-impl.ts)

Description

scValToString decodes an scvAddress of contract type into a raw 64-character hex string rather than the canonical C… StrKey (stellar-impl.ts:384-396):

if (addr.switch() === xdr.ScAddressType.scAddressTypeAccount()) {
  return StrKey.encodeEd25519PublicKey(addr.accountId().ed25519())
}
return Array.from(addr.contractId() as Uint8Array)
  .map((b) => b.toString(16).padStart(2, '0'))
  .join('')

The account branch is correct; the contract branch is not. StrKey.encodeContract is imported-adjacent but never called anywhere in the file. Every event field holding a token contract address — created.tokenAddress (:483), meta.tokenAddress (:489), mint.tokenAddress (:493), burn.tokenAddress (:498) — is therefore stored in an encoding no other part of the system speaks.

Downstream breakage, re-verified against the current tree:

  • Per-token history is always empty. getTokenEvents filters with event.data.tokenAddress === tokenAddress (:1336) where the argument is a C… StrKey supplied by the UI. Hex never equals StrKey, so the filter matches nothing and the history view renders empty for every token that has events.
  • The explorer's index search is broken. TokenExplorer.tsx:250-255 pulls event.data.tokenAddress from the created-events list and passes it to loadTokenByAddress(...), which reaches new Address(hexString) — that throws, and the user sees "Token not found at this index" for a token that exists.
  • Explorer links and address displays are meaningless. TokenExplorer.tsx:91-99 builds its indexToAddress and addressToMeta maps from the same hex values, and useTokenDashboard.ts:72-74 attaches them to every dashboard row as address. Anything rendering or linking that value emits a dead link and an address no block explorer will resolve.
  • There is no test coverage on the decoder at all — no test file in frontend/src references scValToString or encodeContract, which is why an encoding bug this consequential survived.

One claim from the original filing is now stale and has been removed: getTokenInfoByAddress no longer depends on this comparison. It routes through resolveTokenInfoByAddress → getTokenInfoByAddressView (:1200, :1260-1285), a real contract view call, and returns an explicit unresolved marker instead of fabricating placeholder name/decimals. Token identity is authoritative today; it is the event-derived address plumbing that is broken.

Tasks

  • Encode contract addresses with StrKey.encodeContract(addr.contractId()) in scValToString, and review the account branch for muxed-account (scAddressTypeMuxedAccount) handling while there.
  • Prefer scValToNative plus a thin formatting layer over the hand-rolled decoder wherever the SDK's canonical conversion suffices, so this class of bug cannot recur field by field.
  • Add unit tests over real XDR fixtures asserting C… for contract addresses and G… for account addresses — the missing coverage is itself part of this defect.
  • Add regression tests proving getTokenEvents returns a created token's events when queried by its StrKey address, and that the explorer's index search resolves to a real token.
  • Verify explorer links, AddressDisplay truncation, and CSV export render canonical StrKey, since all three consume the same values.

Acceptance Criteria

  • Every address surfaced in events, per-token history, dashboard rows, CSV export, and explorer links is a canonical StrKey string.
  • The per-token history view is populated for a token with events, proven by test.
  • Searching the explorer by token index resolves to that token rather than "Token not found at this index", proven by test.
  • scValToString has direct unit-test coverage for the address branches it decodes.

Re-verified and sharpened on 2026-08-19 during the 30-issue codebase audit tracked in ISSUES.md.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Third CampaignCampaign: Third CampaignauditFrom the ISSUES.md codebase auditfrontendseverity: highBroken core feature or exploitable abuse vector

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions