Hey @igorveras1 - I am leaving my research about the proposal here in this thread - so the others can use it to
What the Proposal Does
Your proposal claims to execute a claim endpoint on 8 contracts that have underlying code IDs using the governance account as executor.
Research Questions and Answers
- Do the on-chain wasm codes of the involved contracts match the compiled source? Yes. All 8 code IDs rebuild byte-for-byte with
cosmwasm/optimizer:0.15.0from upstreammany-things/cw-hyperlanetagv0.0.7-rc0. - Is
claim_ownershipmalicious? No. It only sets the owner to governance and emits one event (as per the above mentioned repository). - Other concerns? Yes, one pre-existing security issue: the deployed multisig ISM predates upstream fix #142, which stops one validator’s signature being counted more than once (see below).
Recommendation: Vote for the proposal. Once governance owns the contracts, it should follow up by migrating the ISMs to fixed code.
Code-hash verification
On-chain Code vs. Release Artifacts
The wasm was downloaded from the LCD (/cosmwasm/wasm/v1/code/<id>). The sha256 of each download equals the chain-reported data_hash, and also equals the official GitHub release many-things/cw-hyperlane v0.0.7-rc0 (published 2024-06-26).
| code_id | Contract | sha256 |
|---|---|---|
| 11371 | hpl_mailbox | b6d789c1a31ee79548fd736bad241dbcd3b8b319d66a776f31479743fe49eb01 |
| 11374 | hpl_ism_multisig | 32b07207c733ba7469f49d321c30cf00bacb8c9560dc92accd35df61e5e3a531 |
| 11376 | hpl_ism_routing | 0881d65f470425290990e53b87044477eaf704e0f2da8481eb4150c6e8c8143c |
| 11377 | hpl_igp | 34313c90c9e08d2c342061412fafe4d064ad783f9be606255d0720590e6fad0b |
| 11378 | hpl_hook_aggregate | 9dfbe1ba3e0dde5ea82cb0daee819214e46afb2ac78075c4f26523e6879a5004 |
| 11379 | hpl_hook_fee | c981467b9af207d09aac90716598ed51c547526b8b82189148a24e1704e7956e |
| 11381 | hpl_hook_pausable | 0f53c4193be46b15eca53ff8cb2004dcc571bf74b345b2b7af2775b6fa99b6c2 |
| 11390 | hpl_warp_native | 34b5deb86937f51d4b04ddc572597b95ffd1b3ce094df8a73dc1cf20babc7e55 |
Reproducible build from source
The code was rebuilt independently on my local machine. Result: all 20 release wasms reproduce byte-for-byte, including all 8 code IDs above, each compared directly against the downloaded on-chain code. To reproduce the build I have the following remarks:
- Source:
github.com/many-things/cw-hyperlanetagv0.0.7-rc0, commiteb791b56db03dae27da5b58faa034274d813bb24. - Builder:
cosmwasm/optimizer:0.15.0. This is the same image the upstreamrelease.yaml/make ci-builduses. - Lockfile: the repo ships no
Cargo.lock, and CI rancargo generate-lockfileat release time. That resolution was recreated in two steps:cargo +nightly -Zunstable-options generate-lockfile --publish-time 2024-06-26T04:55:00Z- Pin the versions that have since been yanked, identified from the dependency paths embedded in the release wasm:
cosmwasm-std/-crypto/-derive/-schema(-derive) 1.5.5,keccak 0.1.5,bytes 1.6.0,bnum 0.10.0.
- Non-output-affecting tweaks: the
integration-testcrate was removed from the workspace, and the[dev-dependencies]sections were stripped. Dev-deps are not compiled into release wasm under resolver v2, and today’s versions need a newer cargo than the one in the image.
Relationship to terra-classic-hyperlane/cw-hyperlane
The fork’s contracts/ and packages/ match upstream main as of January 2025, not the deployed tag. The fork contains 4 upstream commits the deployed code lacks:
| Upstream PR | Change | Severity |
|---|---|---|
| #142 | Multisig ISM: stop counting duplicate validator signatures | High (see §4) |
| #138 | Mailbox Process event emits origin domain instead of local domain |
Cosmetic |
| #139 | Pausable ISM event name fix | Cosmetic |
| #143 | Allow unsetting ISM/hook | Feature |
A build of the fork’s current main would not match the on-chain hashes. The deployed code is exactly upstream v0.0.7-rc0, which is also what the fork’s own deployment docs state (cw-hpl upload remote v0.0.7-rc0).
Pre-existing issue: multisig ISM duplicate signatures (code 11374)
In the deployed v0.0.7-rc0 contracts/isms/multisig/src/query.rs::verify_message, every signature from an address in the validator set decrements the threshold. There is no check for a validator that has already been counted:
for signature in metadata.signatures {
let pubkey = deps.api.secp256k1_recover_pubkey(&hashed_message, &signature[..64], signature[64] - 27)?;
if validators.contains(ð_addr(pubkey.into())?) {
threshold -= 1;
if threshold == 0 { break; }
}
}
Impact: the relayer supplies the metadata. Repeating one validator’s valid signature N times therefore satisfies an N-of-M threshold. A single compromised or malicious validator key on the ETH, BSC or SOL inbound set could get arbitrary inbound messages accepted, including warp transfers that release native LUNC/USTC.
Upstream fixed this in PR #142 (commit d07e55e, 2024-11-11) using a HashSet of matched validators. The fix is present in the fork’s source but not in the deployed code.
Recommended Follow-Up
After this proposal passes, governance should migrate the three multisig ISMs, and optionally the mailbox and pausable ISM, to a verified build that includes #142.