H10X

Bug bounty · Hedera testnet · ended 6 November 2026

No critical issue in the vault

For the bug bounty we offered $2,000 in HBAR to anyone who could steal from the H10X vault, mint H10X without putting the basket in, or seriously alter what backs it, from an account without the team's keys. Nobody could. Every report was checked against the source code and the live networks.

The vault has had a self-review by the H10X team and this public bug bounty. It is not an independent audit.

0critical issues

no theft, no mint without the basket, nothing that alters H10X.

6researchers

who sent 13 findings, grouped below into 12 topics.

17restricted functions tried

one testnet account tried every owner, guardian and rebalancer function: all reverted.

0changes to the contract

the fixes were in our tooling, monitoring, tests and documentation.

Every finding

FindingReported byAssessmentWhat we did
Wipe keys on WBTC and WETH could burn the vault's balanceKupia · Juan AlfonsusInformational (current basket)The key is held by contract 0.0.9675688, an ownerless ERC-20 to HTS wrapper whose only wipe call burns the caller's own tokens when unwrapping: it can't burn the vault's. New basket rule, enforced by our tooling: a wipe key is only accepted if it's held by a reviewed contract that can't burn the vault's balance. Our monitoring now also alerts if a component's backing per H10X drops without a rebalance.
The vault has no auto-renew account and 0 HBAR, and expires on 4 January 2027Juan AlfonsusOperationalHedera doesn't enforce expiry or renewals today. When it does, the renewals of the vault and of the H10X token will be paid from the vault's own balance, so we fund it with HBAR, and our monitoring alerts if that balance runs low.
The per-trade cap applies per call, and the multisig chooses routes and minimum outputsKupiaKnown trust assumption (F-1)Already documented in the review: the 2-of-3 multisig is trusted with rebalancing. Our monitoring checks every proposal before it's signed: routes through tokens outside the basket, low minimum outputs and, now, amounts above the cap.
After a weight change to 0, a rebalance runs without the per-trade capFranklynInformationalA swap never sells more than the amount the signers approved, trades sized within the cap are unaffected, and the owner and the rebalancer are the same multisig. Our monitoring now flags proposals above the cap for tokens that still have weight. New test.
Setting the fee recipient to the vault itself makes claimFees reverthayokakoweda75Informational (owner only)Only the multisig can do it, nothing is lost, and it's fixed by setting a real recipient again. Our tooling now refuses the vault as recipient and our monitoring flags it. New test.
issue and redeem with the vault as recipient reverthayokakoweda75InformationalThey revert with an explicit error, which is the safe outcome: otherwise the caller would be donating to the vault. New test.
A donation above the signed margin delays an exit by one roundhayokakoweda75Documentation (known, F-8)The behaviour was already documented as F-8. The review now says that its live verification ran 1.2.0, and how 1.3.0 differs.
The mutation-testing harness isn't in the repositoryhayokakoweda75DocumentationThe review, this site and the whitepaper now say that the 35-of-36 result comes from the reviewers' suite.
Could a component's admin key add a blocked key type later?FranklynNot possible on HederaA key that is absent when a token is created can never be added, not even by its admin (HIP-540). The admission checks hold for the component's whole life.
The redeem sentinel doesn't enforce skipMask = 0FranklynInformational (affects only the caller)Left unenforced on purpose: with a deleted component and a configuration that keeps changing, the sentinel plus a mask is the only way out. Our redeem tool refuses the combination.
freezeDefault isn't checked when adding a componentAnonymous researcherNot possible on HederaA token can't be frozen by default without a freeze key (all 172 such tokens on mainnet and all 8,626 on testnet have one), and the vault rejects components with a freeze key. Our test mock now matches the network. New test.
claimFees can't succeed on mainnetMuhammad HarleyNot an issueThe recipient's address was converted to the wrong account: 0x…9dfcfc is 0.0.10353916, our fee account, which has been associated with H10X since October.

One report also said that the repository runs 122 tests. A clean forge test of the public commit runs 124, and 128 with the 4 tests added after the bounty.

What happened on testnet

The testnet vault ran the same code as the mainnet vault, with our keeper keeping its pools at the NAV. One account tried 17 restricted functions one by one (fees, components, weights, roles, pausing, rebalancing, initialization and seeding), and every call reverted, as did burnStrayShares, which had nothing to burn. It then called claimFees, which anyone can call: the testnet fees went to the configured fee account, as they should. Apart from our own keeper's normal issues and redemptions, nobody issued or redeemed, nothing left the vault outside those operations, and its backing per H10X never dropped.

What changed

Rewards

No report met the critical criteria, so the $2,000 reward was not paid. We are sending thank-you rewards in HBAR to the researchers whose reports were most useful, and we will contact each of them directly.

Thank you

To Kupia, hayokakoweda75, Franklyn, Muhammad Harley, Juan Alfonsus and the anonymous researcher, for their time and for keeping their reports private until we answered.