--- eip: 8244 title: Contract-Hosted Application HTML description: A view-only interface for a contract to serve its own self-contained HTML dapp. author: z0r0z (@z0r0z), ndavd (@ndavd), Zefram Lou (@ZeframLou), Ronan (@wighawag) discussions-to: https://ethereum-magicians.org/t/erc-8244-contract-hosted-application-html/28407 status: Draft type: Standards Track category: ERC created: 2026-04-30 requires: 1193, 6963 --- ## Abstract This proposal defines a single view function, `html()`, that lets a smart contract serve a complete, self-contained HTML application directly from its own state. A wallet, browser extension, or block explorer that already exposes an [EIP-1193](./eip-1193.md) provider can fetch the document with one `eth_call` and render it. Off-chain hosting (HTTP, IPFS, NPM, CDN) is not required, and any external resource a document does reference is integrity-checked, so no mutable second trust domain is introduced. ```solidity function html() external view returns (string memory); ``` This proposal does not prescribe how the bytes are stored on chain. It prescribes only the interface and the constraints on the returned document that allow a generic client to render it safely. ## Motivation Every "decentralized" application today is split across two trust domains: the contract, which is deterministic and verifiable, and the frontend, which is hosted somewhere mutable (HTTP, IPFS pin, S3, NPM dependency tree). Users routinely sign transactions produced by code their wallets did not verify. This split is the root cause of phishing forks of legitimate frontends, gateway poisoning, malicious build-time dependencies, expired or hijacked domains, and frontends that drift away from the contracts they claim to drive. If the contract serves its own UI, the wallet can fetch it through the same RPC it already trusts, and the dapp lives in the same trust domain as its bytecode. There is no second domain to phish and no dependency tree to compromise. The pattern is already viable: the 24576-byte runtime code limit set by [EIP-170](./eip-170.md) is routinely circumvented by storing the document across multiple data contracts (e.g. SSTORE2-style) and concatenating their bytes at read time. Self-contained dapps that implement keccak256, ABI encoding, ENS resolution, and [ERC-20](./eip-20.md) calls in inline JavaScript fit comfortably in such budgets. What is missing is a standard interface so that any client can find and render any such UI. ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. ### Interface A compliant contract MUST implement: ```solidity interface IContractHostedApp { /// @notice Returns the contract's self-contained HTML application. /// @return A complete UTF-8 encoded HTML document. function html() external view returns (string memory); } ``` The function MUST be `view`, MUST NOT revert under normal operation, and MUST return a valid UTF-8 byte sequence. How the bytes are stored is out of scope. ### Registry Interface For contracts that cannot implement `html()` directly (already deployed and immutable), a registry contract may store HTML on their behalf. A conforming registry implements: ```solidity interface IContractHostedAppRegistry { function html(address target) external view returns (string memory); } ``` A client MAY fall back to a known registry when a direct call to `target.html()` returns empty or reverts. A registry MAY support versioned reads via an overloaded `html(address target, uint256 version)` to allow clients to query historical document versions. A registry MAY also support cross-authored reads via an overloaded `html(address author, address target)`, where `author` is the address that registered the document on behalf of `target`. Write access and authorization rules for updating registry entries are out of scope for this proposal and left to the contract's implementer. The registry and the standalone interface share the same document constraints defined in this proposal. ### Document The string returned by `html()` is the _document_. **Origin contract.** The document MUST be able to identify the contract that produced it. The RECOMMENDED method is to embed the contract address as a JavaScript constant at write time, made deterministic by deploying through CREATE2 / CREATE3 or by writing the document after the contract address is known. The following properties are RECOMMENDED: 1. **Self-contained.** The document SHOULD prioritize embedded resources, such as `data:` URIs and `blob:` URIs constructed from in-document strings. Any external resource SHOULD be integrity-checked — for example with Subresource Integrity (SRI) (`