Skip to main content

Integrate Hull in Your Frontend

This page has two halves with different levels of certainty.

The first half describes what a frontend will read from Vessel at Gate-0: series terms, NAV, maturity, and remaining issuance capacity under the subordination floor. As of 2026-08-29 the public repository (github.com/Lemma-Development-Labs/vessel) contains only a README and a LICENSE. No contracts, ABIs, or deployed addresses are published. Every function name, return shape, and address in that half is therefore a design-stage placeholder, marked as such. Do not build against it until the contracts are published and the markers are removed.

The second half is guidance that applies now to any frontend on Monad, Vessel or otherwise. It is drawn from the Monad developer documentation and holds regardless of what Vessel ships.

Design stage

Vessel is experimental software in testnet and unaudited. Nothing on this page is a stable interface. The Vessel-specific commands are templates with placeholders, not something to paste into a build.

What a frontend reads at Gate-0

The litepaper fixes what an integrator needs to display for a Hull series. The values are defined; the calls that return them are not yet public.

ValueDefined byRead via
Series rate r_HContract parameter: r_H = clamp(EWMA_30d(net funding APR) × (1 − h), 0, r_cap), h = 40%, r_cap = 15% APRview call, name pending UNVERIFIED — PENDING GATE-0
MaturityFixed-maturity series, 4-week at launchview call, name pending UNVERIFIED — PENDING GATE-0
Hull NAVContinuous NAV; daily accrual A_H = r_H × H × Δtview call, name pending UNVERIFIED — PENDING GATE-0
Remaining Hull capacitySubordination floor B / (H + B) ≥ 20%, enforced at all timesview call, name pending UNVERIFIED — PENDING GATE-0

The rate is a contract parameter, not a yield forecast. A frontend must label it as the series' fixed rate, set at issuance, and must not present it as expected or historical performance.

Series terms

Template. Replace every bracketed token when the ABI is published.

# PENDING: contract address and function name are not published as of 2026-08-29
cast call <HULL_SERIES_ADDRESS> "<seriesTerms()(...)>" \
--rpc-url https://testnet-rpc.monad.xyz

What the response has to carry, per the litepaper: the series rate r_H, the maturity timestamp, and the issuance date. The exact return tuple is unpublished UNVERIFIED — PENDING GATE-0.

# PENDING: function name unpublished
cast call <HULL_SERIES_ADDRESS> "<nav()(uint256)>" \
--rpc-url https://testnet-rpc.monad.xyz

Hull NAV accrues at the fixed series rate. Display it as principal plus accrued fixed yield to date. Under the shortfall ordering, Ballast NAV absorbs losses first, then the Reserve, and only then is Hull principal impaired; a frontend showing Hull NAV below principal is showing a credit event, and should say so plainly.

Maturity

# PENDING: function name unpublished
cast call <HULL_SERIES_ADDRESS> "<maturity()(uint256)>" \
--rpc-url https://testnet-rpc.monad.xyz

Hull redeems principal plus fixed yield at maturity. Early exit is by secondary sale only. A frontend should not offer a redeem action before maturity, because the contract does not have one.

Remaining capacity under the floor

New Hull issuance is constrained by the subordination floor. Given Hull notional H and Ballast NAV B, the floor B / (H + B) ≥ 20% bounds how much additional Hull can be issued. Whether the contract exposes a single capacity view or the frontend derives it from H and B is undecided UNVERIFIED — PENDING GATE-0.

# PENDING: either a direct capacity view, or read H and B and derive
cast call <ENGINE_ADDRESS> "<hullCapacity()(uint256)>" \
--rpc-url https://testnet-rpc.monad.xyz

If deriving, the arithmetic follows from the floor alone: the maximum Hull notional for a given B is H_max = B × (1 − θ_min) / θ_min with θ_min = 20%, so H_max = 4 × B, and remaining capacity is max(H_max − H, 0). This is a consequence of the published invariant, not a published function.

Addresses

Contract (testnet)AddressActions
EngineUNVERIFIED — PENDING GATE-0
Hull series (current)UNVERIFIED — PENDING GATE-0
BallastUNVERIFIED — PENDING GATE-0
ReserveUNVERIFIED — PENDING GATE-0

Once addresses are published, confirm code is present before wiring anything:

cast code <ADDRESS> --rpc-url https://testnet-rpc.monad.xyz

Testnet chain ID is 10143. The primary testnet RPC is https://testnet-rpc.monad.xyz, rate-limited to 50 requests per second, with 25 per second for eth_call and eth_estimateGas. A frontend that polls NAV on every block will hit the eth_call limit; batch through Multicall3 or poll on a timer.

Monad rules that apply now

Everything below is independent of Vessel. It is how a Monad frontend has to handle gas, balances, and confirmation, and getting it wrong costs users money.

Gas is charged on the limit

On Monad, gas_paid = gas_limit × price_per_gas. The user pays for the limit set on the transaction, not the gas the execution used. This follows from asynchronous execution: leaders build blocks before executing them, so consumption is not known at inclusion time. See the network page for the full parameter set.

Consequences for a frontend:

  • Set explicit gas limits on every transaction. Do not leave the limit to a wallet default.
  • Keep the estimation buffer at or under about 10 percent. A 50 percent safety margin on Ethereum is free; on Monad it is paid in full.
  • Never display a cost derived from gasUsed on the receipt. The number the user paid is gasLimit × effectiveGasPrice. Showing gasUsed × price understates the real cost.
  • Hardcode 21,000 for native MON transfers. That is always the exact cost; there is nothing to estimate.
  • Guard the revert path. If eth_estimateGas reverts, some wallets fall back to a very large limit, and on Monad the user pays that entire limit. Surface the revert to the user rather than letting the transaction proceed with a fallback limit.

eth_call and eth_estimateGas simulate against speculative state and return accurate results, so estimates themselves are reliable. The hazard is what happens to the number after estimation.

The reserve balance and new accounts

Two Monad behaviours shape onboarding UX.

10 MON reserve floor. Each EOA has a 10 MON reserve balance floor. Accounts at or below it are limited to roughly one transaction per 1.2 seconds. A frontend that funds a fresh wallet and then fires a batch of transactions will see them throttled. Check the balance before sequencing multiple sends, and tell the user when the account is below the floor.

Newly funded accounts. Consensus validates transactions against a state view delayed by three blocks (D = 3). A freshly funded account cannot send until its funding is three blocks old, about 1.2 seconds at 300 ms blocks. Onboarding flows that fund a wallet and immediately submit a transaction will fail on the first attempt. Wait for the funding transaction to be three blocks deep, or simply wait 1.2 seconds, before enabling the next action.

Block tags and UI transitions

Monad block states map to standard tags: latest is speculative (proposed), safe is validator-backed (voted), finalized is irreversible. Speculative finality is 300 ms; full finality is 600 ms.

  • Use finalized for any transition the UI cannot walk back: marking a deposit as complete, updating a displayed balance the user will act on, showing a Hull position as held.
  • Use latest for optimistic feedback: a pending indicator, a provisional NAV refresh, a toast.

The gap between the two is 300 ms. There is no UX reason to accept reversibility risk to save it.

Same-call receipts

eth_sendRawTransactionSync returns the receipt in the send call itself. For a frontend this removes the send-then-poll loop: submit, receive the receipt, render. Pair it with the block-tag rule above; a receipt from the sync call tells you the transaction was included, and the finalized tag tells you it will stay included.

Cold access costs

Cold account access costs 10,100 gas (Ethereum: 2,600) and cold storage access 8,100 (Ethereum: 2,100); warm access is 100, unchanged. This matters for a frontend only in that gas estimates for first-touch operations run higher than Ethereum intuition suggests. Do not trim a Monad estimate toward an Ethereum number.

What this page cannot yet tell you

  • Contract names, function signatures, return types, and ABIs. None are published.
  • Deployed testnet addresses for the Engine, Hull series, Ballast, or Reserve.
  • Whether remaining Hull capacity is a direct view or derived client-side.
  • Event signatures for indexing deposits, issuance, and accrual. The indexing pipeline (see docs.envio.dev/docs/HyperIndex/envio-cloud-cli) requires a deployed and explorer-verified contract before an ABI can be imported, so indexing guidance waits on the same publication.
  • Any frontend SDK or package. None exists.

When the contracts are published, this page will replace each placeholder with the verified call and drop the markers. Until then, treat the second half as binding and the first half as a preview of shape.

Verified from: vessel.wtf/litepaper · vessel-repo · monskills/gas · monskills/concepts · monskills/addresses · docs.monad.xyz — Sat Aug 29 2026 00:00:00 GMT+0000 (Coordinated Universal Time) · How we verify this site →