Whitepaper

ClosePrint

This paper does not forecast returns. Mainnet is not live. Testnet 46630 is not funded yet. How to use the site

Abstract

ClosePrint is a public NAV and receipt layer for Robinhood Stock Tokens on Robinhood Chain. It publishes the official close, the onchain price, and the gap between them. It also wraps NVDA into nvda.print, a receipt whose balanceOf already includes the live corporate-action multiplier.

It is not a broker. It is not a launchpad. There is no protocol token. The receipt is the primitive.

Readers sign from their own wallet. Gas is ETH. ClosePrint holds no admin keys over user funds.

Problem

After a split or dividend, an explorer still shows the raw token balance. That number is the old share count. The live economic amount is raw times uiMultiplier, divided by 1e18, truncated toward zero. People who treat the explorer figure as shares get the wrong size.

The official close comes from a Chainlink stock-token feed. The onchain price comes from a Uniswap v3 token/USDG pool. After hours and on weekends the close is frozen and the pool can still move. The difference is the gap. ClosePrint prints that gap. It does not invent a venue to trade it.

Scope

ClosePrint reads five names on the board: NVDA, AAPL, TSLA, SPY, QQQ. The wrapper is NVDA only.

It does not ship a launchpad. It does not ship a meme or utility token. It does not ship a generic DCA agent. It does not create a new AMM, DEX, or pool. The wrapper has no admin upgrade path. There is no fee at launch.

System

Three contracts, no shared treasury.

  • PrintLens is view-only NAV. No admin. No storage writes after construct.
  • PrintWrapper holds raw NVDA and mints nvda.print. Internal books stay in raw units. balanceOf and totalSupply are UI amounts.
  • GapRouter is a guard, not a venue. It forwards settler calldata and never holds user funds across transactions.

Chainlink close and Uniswap v3 TWAP feed PrintLens. PrintLens supplies gap and caps to GapRouter. GapRouter forwards to a settler or 0x. PrintWrapper mints nvda.print to the wallet. Solidity 0.8.24, Foundry, OpenZeppelin. The wrapper has no proxy, no owner, and no pause.

Prices

Close is the Chainlink stock-token latestRoundData answer, scaled to 18 decimals. The feed already quotes total return per token. ClosePrint never multiplies that answer by uiMultiplier().

Onchain is the Uniswap v3 token/USDG TWAP over 30 minutes. If that window is not ready, the board shows spot and marks it SPOT. Spot is display only. The gap router needs a live TWAP.

Gap is (onchain minus close) in basis points. One basis point is 0.01%. Quote asset is USDG at 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168, 6 decimals.

If close is $180.00 and onchain is $179.10, the gap is about −50 bps. The token is cheap vs close. If onchain is $180.90, the gap is about +50 bps. The token is rich vs close.

Invariants

  1. Chainlink RHC equity feeds already include the multiplier. closePrice is the feed answer scaled to 18 decimals. Do not multiply it by uiMultiplier().
  2. economicBalance = mulDiv(rawBalance, uiMultiplier, 1e18). Truncates toward zero.
  3. Wrapper balanceOf and totalSupply are UI amounts (raw shares scaled by the live multiplier). Internal accounting is raw deposited units.
  4. Gap router is a guard, not a venue. It never holds user funds across transactions.

Invariant 2 is the only legal way to turn a raw explorer balance into an economic size. Multiplying a Chainlink answer by the same multiplier is a bug.

Wrapper

A holder approves the wrapper, then wraps. The wrapper pulls raw NVDA and mints nvda.print. Unwrap burns the receipt and returns the raw token. Unwrap is available anytime.

Only NVDA is wrapped. The wrapper has no owner and no upgrade path. After a corporate action, raw NVDA on an explorer and nvda.print in a wallet can look different. That is the multiplier.

Router

The router forwards 0x calldata, or mock settler calldata in tests. It does not create a pool. The fill price is the Uniswap or settler price, not the close.

What it checks before it fills:

  • Gap must be at least 25 bps, or the trade does not start.
  • Max $2,000 per trade, as 18-decimal USD.
  • Aborts if the fill is more than 50 bps worse than the lens price.
  • Aborts if the close is older than 72 hours.
  • Needs a live TWAP and pool liquidity above zero.

There is no fee at launch. If a fee ever exists, it is 1 to 5 bps on gap trades, paid in USDG.

Display

Default site mode reads mainnet, chain ID 4663, RPC https://rpc.mainnet.chain.robinhood.com. Explorer https://robinhoodchain.blockscout.com. Close, Onchain, and Gap come from that chain even while write contracts live on testnet. Lens math runs client-side until a mainnet lens exists.

When NEXT_PUBLIC_CLOSEPRINT_CHAIN=46630 or CLOSEPRINT_CHAIN=46630, Close, Onchain, and Gap are read from the deployed PrintLens on testnet. RPC https://rpc.testnet.chain.robinhood.com. Explorer https://explorer.testnet.chain.robinhood.com. Testnet lists NVDA only.

Agents

The MCP server can read prints and economic balances. Write tools stay off unless every gate is set: CLOSEPRINT_ENABLE_WRITES=1, CLOSEPRINT_CONFIRM=1, a session USD cap, and a local signer. Keys are never stored or transmitted. See mcp/README.md.

Risks

A feed outage freezes the close. A thin pool can move against a fill even inside the 50 bps abort. The close is stale on weekends on purpose. The gap can stay open or widen. You pay the settler, not the close. Gas is ETH, paid by you.

Wallet custody is yours. Testnet contracts can have bugs. Testnet mocks are worth nothing. Do not send mainnet money to a testnet address. Mainnet contracts are not deployed yet.

Status

PrintLens, PrintWrapper, and GapRouter are not live on testnet 46630. There are no wrap or gap transaction hashes yet.

How to click through each screen is in /learn.