Date: 2026-06-11
Class: SEAMS / cross-chain message trust - HAND-ROLLED receive handler (the forward-pointer from the Venus cycle)
Source case: USDT0 HyperLiquidComposer_V1_FeeToken, HyperEVM (chainid 999) 0x80123Ab57c9bc0C452d6c18F92A653a4ee2e7585. WALK-CLEAN.
Companion to: crosschain-consumer-msgtrust-walk-venus-cycle-2026-06-11.md (the clean-inheritance dead-end lesson this one extends).
The Venus lesson said: clean LzApp/OFTCore inheritance = LOW yield; the yield is in HAND-ROLLED handlers and the COMPOSE/RETRY second-class path. This cycle operationalized that:
1. In a multi-contract OFT ecosystem, the 23 standard token OApps (OUpgradeable/OAdapterUpgradeable) are clean OFTCore inheritance - skip them fast (read ONE verified impl to confirm inheritance, then move on).
2. The real hand-rolled surface hides in the SATELLITE/COMPOSER contracts that implement ILayerZeroComposer/IOAppComposer DIRECTLY: HyperCore composer, MultiHop hub composer. These re-implement the trust gates by hand.
3. Audit-reports repos are a fast index to the hand-rolled pieces: a report titled "...Composer" / "...Multihop" points straight at the non-inherited handler. (Everdawn-Labs/usdt0-audit-reports listed Guardian HyperLiquidComposer + Multihops reports - those named the hand-rolled contracts.)
4. Verified source for non-EVM-mainnet chains is reachable WITHOUT an Etherscan key: Blockscout/Hyperscan ?module=contract&action=getsourcecode returns full multi-file source (use AdditionalSources). Worked for HyperEVM (hyperscan.com) and Arbitrum/ETH (blockscout).
if (OFT != _oft) revert ... (or equivalent immutable trusted-source compare). USDT0 had it at line 97. The immutable OFT is the hand-rolled stand-in for _assertPeer.nonReentrant + delete failedMessages[guid] is belt-and-suspenders. Rarely the seam on LZ v2 compose.cast-read them and assert they equal the genuine in-scope OFT + genuine LZ endpoint + correct admin Safe. Cross-check: composer.ENDPOINT() == OFT.endpoint() (consistency).if (msg.sender != ENDPOINT) revert OnlyEndpoint() outer; if (msg.sender != address(this)) revert OnlySelf on any inner privileged step. Both present here.refundToSrc(guid) is PERMISSIONLESS - but safe because it only acts on a failedMessages[guid] that lzCompose itself populated (post a+d), refunds to the stored composeFrom, and deletes first. The lesson: a permissionless retry/refund is only a finding if it can (i) accept a forged source, (ii) reach a privileged action, or (iii) double-spend. Check those three; "anyone can call it" alone is NOT a bug.tx.origin fallback in refund paths: looks scary, but here it only routes a refund of the USER's own stuck value; not an extraction primitive. Note-and-move-on.OFT==_oft compare entirely (relies only on msg.sender==endpoint). That is the real takeover: endpoint will deliver a compose from ANY OApp that names this composer as its compose target, so without the _oft compare an attacker-OApp could forge amountLD/composeMsg. USDT0 closes this; the NEXT target may not.handleTransfers...), or whose refund path credits an ATTACKER-chosen address rather than the stored composeFrom.cast-reading peers(eid) per new chain (checked Plasma 9745 + Arbitrum hub here - both fully wired, clean).Composer/router contracts are frequently NOT in the OFT program's named asset list even when the token+OApp are. Confirm the exact contract is in scope before treating a composer finding as payable; do not assume a catch-all. And per the banked LayerZero rule, consumer-side misconfig routes to the consumer's program, never LayerZero's.
Clean-inherited OFTCore = skip. Hand-rolled ILayerZeroComposer = read every line and check (a)+(d) explicitly plus the (e) refund/retry path for the three takeover conditions. USDT0's HyperLiquidComposer is a POSITIVE reference implementation of a correctly-hand-rolled compose handler - bank it as the "what right looks like" baseline to diff future composers against.