From review of #453 (comment 1, comment 2). Confirmed still valid at HEAD. Target: L1 nexum-sdk (+ nexum-runtime). The security-relevant behaviour is correct today; these harden fragile invariants.
1. Bound block_on's poll loop (robustness)
nexum-sdk/src/chain/provider.rs's block_on loops unbounded, relying on the invariant that a host call always resolves in one poll (HostTransport::call returns ready(...) today). A future alloy version chaining a retry/backoff layer, a tower::Buffer, or a pubsub / multi-await path would turn this into a silent busy-spin that burns the guest's entire gas / metering budget with no diagnostic. Cap the loop and panic with a clear message ("future did not resolve synchronously after N polls") - a fail-loud break of the one-poll invariant beats a silent hang.
2. Guard ChainMethod drift (security)
nexum-sdk/src/chain/method.rs's ChainMethod is hand-duplicated byte-for-byte against nexum-runtime/src/host/component/chain.rs's ChainMethod (18 variants, same #[strum(serialize=...)] strings), with no shared source or CI check. The guest allowlist security property ("closed enum = allowlist") depends on this matching the host dispatch table exactly. Silent drift in the SDK-diverges-from-host direction could reopen the very gap this PR closes, undetected until runtime. Extract ChainMethod into one shared definition both sides depend on, or add a cross-crate test that diffs both enums' variant strings so drift fails CI loudly.
Acceptance criteria
block_on fails loud (bounded + diagnostic) rather than spinning unbounded.
ChainMethod has a single source of truth, or a drift-detecting test; divergence fails CI.
1. Bound
block_on's poll loop (robustness)nexum-sdk/src/chain/provider.rs'sblock_onloops unbounded, relying on the invariant that a host call always resolves in one poll (HostTransport::callreturnsready(...)today). A future alloy version chaining a retry/backoff layer, atower::Buffer, or a pubsub / multi-await path would turn this into a silent busy-spin that burns the guest's entire gas / metering budget with no diagnostic. Cap the loop and panic with a clear message ("future did not resolve synchronously after N polls") - a fail-loud break of the one-poll invariant beats a silent hang.2. Guard
ChainMethoddrift (security)nexum-sdk/src/chain/method.rs'sChainMethodis hand-duplicated byte-for-byte againstnexum-runtime/src/host/component/chain.rs'sChainMethod(18 variants, same#[strum(serialize=...)]strings), with no shared source or CI check. The guest allowlist security property ("closed enum = allowlist") depends on this matching the host dispatch table exactly. Silent drift in the SDK-diverges-from-host direction could reopen the very gap this PR closes, undetected until runtime. ExtractChainMethodinto one shared definition both sides depend on, or add a cross-crate test that diffs both enums' variant strings so drift fails CI loudly.Acceptance criteria
block_onfails loud (bounded + diagnostic) rather than spinning unbounded.ChainMethodhas a single source of truth, or a drift-detecting test; divergence fails CI.