Prerelease. ABX FS is early, unaudited software. It may have bugs, and we do not guarantee it is bug-free. What you publish is public and permanent, and on production chains real funds are at risk. Details
Skip to Content
ABX FS
Reference

Project presentation and native reads

Select a project's marketplace content, freeze presentation choices, and read stored bytes from Solidity.

Edit on GitHub

Project presentation controls animation_url, a content field commonly used by NFT marketplaces, for orgs created by a factory with projectPresentation. It is separate from publishing: versions remain append-only, and presentation changes do not rewrite stored content. Check deployment status for the current generation and the original factories retained for older orgs.

Choose a delivery method

MethodWhat the token rendersWhen to use it
ChainGatewayA chain-specific URL for the selected root and pathThe on-chain default; websites, larger files and content with dependencies
EmbeddedThe selected file's bytes, embedded by ABX in metadataSupported HTML, SVG, image, audio or video payloads with a suitable caller budget
IPFSipfs://<cid>/<path>, or an explicit subdomain gateway URLAn explicit creator choice, with pinning arranged separately

auto is a CLI/SDK recommendation, not a fourth on-chain mode. Its configurable tooling policy defaults to 100 KiB of inspected content; it writes Embedded for suitable supported payloads with no detected dependencies, otherwise ChainGateway. This is a recommendation, not a contract limit or a promise that every RPC can render the complete metadata. The current presentation generation places no fixed byte, chunk or gas policy on explicit Embedded. Natural caller gas and RPC response limits still apply. The superseded presentation generation had an 8,192-byte/32-chunk limit; older original factories have no presentation capability.

Raw storage and FastLZ storage decode natively. File-level codecs such as gzip need off-chain decoding and cannot use Embedded. text/uri-list is reserved for locator output, not embedded content. Relative/external references and detected network or opaque dynamic code favor a gateway origin. Inline JavaScript can qualify, but static inspection cannot prove arbitrary code self-contained: review runtimeUncertain, residualDependencies, and readReach in the plan.

Auto never selects IPFS. On-chain IPFS derivation cannot decode file-level codecs, including a known changed codec file elsewhere in the derived directory root. The planner blocks these known incompatibilities and proven absent configured targets before publication. A directory URL does not require index.html; MIME and Auto size preferences do not restrict an explicit IPFS choice. Planning does not scan all unchanged siblings or guarantee complete root derivation.

Choosing IPFS computes a CID; it does not pin anything or promise availability. The creator must pin the content and keep it available. An empty IPFS endpoint uses ipfs://; a base such as https://dweb.link produces https://<cid>.ipfs.dweb.link/.... An empty chain endpoint uses the generation's default gateway; a custom chain base must serve /g/cid/<chain>/<root>/<path>. Use HTTPS bases without a trailing slash.

A first publication uses Auto when its org supports presentation, including an already-minted empty project. Tooling suggests index.html, otherwise the sole file, otherwise the directory root. An explicit path, including "", takes precedence. Deliberately preconfigured source and method choices are preserved independently; setting endpoints alone does not disable initial Auto selection.

Later upload --project-id and update preserve the saved source, method and endpoints unless --presentation or --presentation-path explicitly changes a choice. They never silently downgrade an owner's method. After publication the CLI checks complete tokenURI with a bounded read pinned to the final confirmed settings transaction, or publication transaction when no settings changed, as well as native preview on update. A failure produces a warning and exact inspection/recovery commands; publication remains successful and must not be repeated. See the CLI commands and SDK planner.

Select the source

Choose Latest, a 1-based Version, or a named Tag, plus an optional path inside that root. Latest follows new publishes; Tag follows tag movements; Version selects one historical root. An empty path selects a file root or index.html in a directory when reading Embedded content. A selected directory likewise reads its index.html. Presentation paths are relative, without empty segments, ./.., backslashes or control bytes, and fit 2,048 UTF-8 bytes, 32 segments and 255 bytes per segment. Explicit invalid targets are blocked before publishing, regardless of delivery method. If a suggested entrypoint exceeds these limits, Auto keeps the directory root and chooses ChainGateway; this does not reject a valid deeper content tree.

presentation inspect reports the exact selected root and path, method, endpoints and locks. presentation preview adds the status, MIME type, payload and dependency analysis without a signer. Native preview and payload analysis do not prove that the full ABX metadata can be serialized within a caller budget. A 100 KiB payload can require close to 50 million gas for complete tokenURI, depending on content and metadata. A Ready URL preview does not check that its remote endpoint is online. Semantic missing or unpublished targets and unsupported codec/MIME states return an empty text/plain payload, encoded by ABX as the inert data:text/plain;base64, animation URI. Actual native read or IPFS derivation failure is surfaced as a typed render failure, and insufficient caller gas can fail the complete metadata read. Inspect diagnostic preview to distinguish these cases; do not treat native preview as a guarantee of complete metadata availability.

Browser and marketplace support for HTML, data URIs and IPFS varies. Preserved bytes and valid token metadata do not guarantee that every viewer can display or execute the content.

Freeze independent choices

Only the project token owner may configure or lock its presentation. Freezing the displayed content is one-way, including for future owners. Three permanent locks can be combined:

LockCommitment
ContentThe reviewed selected root and path, even if Latest or a Tag later moves
MethodChainGateway, Embedded or IPFS
EndpointsThe configured chain and IPFS endpoint bases

Every lock requires an explicit commitment to the reviewed state of its selected dimensions. Dry-run the exact CLI lock command, review the output, then copy its expectedCommitment into --expected-commitment for submission. The contract checks it when the transaction executes; changed selected state requires a fresh review. SDK callers read the commitment at the preview's block. Locks survive transfers and have no force override. Publishing later versions remains possible. Freezing content alone does not freeze its delivery method or the services an endpoint depends on.

external_url remains separate: it uses the org's link renderer and abxfs.view override. A view override cannot bypass presentation locks or replace the new animation_url. Legacy token links describes orgs whose animation and external links both use that older renderer.

Native Solidity reads

ContentReader is a stateless companion with immutable file/directory store addresses and no roles or ETH. It adds no mutable content registry and changes no CIDs. Its view calls return MIME type and bytes:

(string memory mime, bytes memory data) = reader.readPath(root, "index.html", 8192, 32);
// Direct file or byte range:
(mime, data) = reader.readFile(fileCid, 8192, 32);
(mime, data) = reader.readFileRange(fileCid, 0, 128, 8192, 32);
// Latest project root; use a 1-based version OR a tag to select history:
bytes32 selected = reader.projectRoot(org, tokenId, 0, "");
(mime, data) = reader.readProject(org, tokenId, 0, "stable", "index.html", 8192, 32);

Native reads support raw and FastLZ storage: FileStore.readChunk decompresses the storage backend. They reject file-level codecs, including gzip, Brotli and Zstandard; use the SDK or chain gateway to decode those. Whole-file reads check recorded byte and chunk totals before allocating content. Range limits include the full decoded sizes of touched boundary chunks, not just returned bytes. Limits bound bytes and chunk reads, not backend gas; Solidity callers containing failures should also cap call gas. projectRoot follows the org's own configure hook, including older orgs; it is a content convenience, not proof of factory registration.

Use stored content in an ABX reader field

AbxContentReader adapts a fixed root/path to ABX's read(address) reader ABI. Deploy one with the reader address, root, path and explicit limits, then encode the adapter as both reader and pointer:

AbxContentReader adapter = new AbxContentReader(address(reader), root, "index.html", 8192, 32);
bytes memory readerValue = abi.encode(address(adapter), address(adapter));
bytes memory data = adapter.read(address(adapter));

Use readerValue as the value of an ABX field configured with its on-chain reader representation. The pointer identifies this fixed adapter; any other pointer is rejected. Its source and limits cannot be redirected after deployment. File codecs remain unsupported. This adapter supplies bytes to an ABX field; it does not give an older ABX FS org the new presentation renderer.

Factory generations stay available

Presentation is a factory-generation capability. Resolve an existing org with client.resolveOrg(org) first. An older generation without projectPresentation reports PresentationCapabilityError rather than borrowing the current contract. A native reader can still read old content using its matching stores; if the store pair differs, use a reader deployed for that pair or ordinary SDK reads.

A replacement factory creates new orgs. Earlier factories, hooks, minters, enumeration contracts and lenses remain registered together in previousGenerations so their orgs can still be listed, read, minted into and published to. Those records are permanent compatibility history, not temporary migration entries.

On this page