# Protocol technical guide

This is the implemented design of the Robinhood Chain Stock Token rewards experiment. The repository contains working Solidity contracts, simulations, tests, and local/testnet deployment tooling. Mainnet deployment is disabled. Verification evidence below is dated September 11, 2026; it is not an external audit or a live deployment claim.

## Architecture: ten components

| Component | Responsibility |
| --- | --- |
| LaunchToken | Mints one billion 18-decimal TOKEN once to an explicit recipient; supports transfers, permit, and permanent burns. |
| RewardFeeHook | Charges the separate reward fee on executed swaps in one immutable TOKEN/USDG pool. |
| FeeVault | Holds backed TOKEN and USDG fee liabilities separately for each calendar epoch. |
| RewardController | Closes epochs, fixes historical reward obligations, and attempts atomic batch settlement. |
| BurnVoteController | Burns approved TOKEN allowances to select the next epoch's Stock Token. |
| StakingRewards | Records historical stake-time and pays eligible users their raw Stock Token entitlements. |
| RobinhoodStockTokenAdapter | Executes governed routes subject to oracle, minimum-output, deadline, pause, and sequencer checks. |
| V4RouteExecutor | Executes an immutable path of one to three real Uniswap v4 pools. |
| LiquidityManager | Owns protocol positions, seals bootstrap liquidity, and constrains subsequent repositioning. |
| RewardHookFactory / HookMiner | Mines and deploys a CREATE2 address whose hook permission bits match the implementation. |

Supporting modules include `BootstrapCurve` for integer liquidity math, `IRewardEligibility` for a production transfer-control integration, and explicitly marked test mocks. The production eligibility implementation remains outstanding.

The reward path is swap → hook → epoch vault → batch TOKEN normalization if needed → Stock Token purchase → historical staking claims. Protocol-owned liquidity is a separate pool of capital. Burn voting changes the next epoch's asset; it does not move or convert rewards already earned.

## Supply and launch configuration

`LaunchToken.INITIAL_SUPPLY` is 1,000,000,000 TOKEN. There is no owner, future mint function, transfer tax, blacklist, or rebase. `burn()` destroys the caller's balance; `burnFrom()` requires allowance. The token's fixed supply ceiling is separate from configurable allocation decisions.

The current simulation candidate is DEEPER / 200M TOKEN / $250 USDG. Its nine ranges begin around a $3,000 FDV, equivalent to $0.000003 per TOKEN. The local/testnet script reserves the configured 200M in LiquidityManager and transfers 800M to the explicitly supplied remainder recipient. This candidate is not a finalized public launch allocation. Low initial capital produces substantial modeled price impact; FDV is a price-times-supply measure, not cash held in the pool.

## Exact swap-fee accounting

The LP fee is 2500 in v4's fee units: 0.25%. The reward fee is 200 basis points: 2%. The hook charges the actual executed **unspecified leg**, before applying the hook adjustment:

```
rewardFee = ceil(abs(executedUnspecifiedDelta) × 200 / 10,000)
```

| Trade | Mode | Reward fee currency | Final trader effect |
| --- | --- | --- | --- |
| Buy TOKEN with USDG | Exact input | TOKEN | Reduces executed TOKEN output |
| Buy TOKEN with USDG | Exact output | USDG | Increases executed USDG input |
| Sell TOKEN for USDG | Exact input | USDG | Reduces executed USDG output |
| Sell TOKEN for USDG | Exact output | TOKEN | Increases executed TOKEN input |

These rules work in either currency-address ordering. Partial fills are charged on execution, not the unfilled request. Zero execution pays zero; rounding upward prevents dust fragmentation from avoiding fees and can exceed 2% proportionally on tiny amounts. Exact-output input already includes the pool's LP charge. Exact-input output already reflects pool execution. Consequently, an exact universal 2.25% surcharge on USDG notional would misstate this design.

The hook transfers the collected ERC-20 to FeeVault through `PoolManager.take`, records the backed fee, and returns a positive unspecified-currency hook delta. The transient hook debit and credit cancel, and the trader's final delta includes the fee. Routers must enforce minimum output or maximum input against that final delta.

Only the configured PoolManager can invoke the hook. The entire pool ID is checked, hook data must be empty, and there are no caller exemptions. Required low fourteen address bits are exactly `0x0044`: `afterSwap` and `afterSwapReturnDelta`. CREATE2 mining includes the actual factory and complete constructor arguments. The hook cannot tax independent pools for the freely transferable TOKEN.

## Epoch state and atomic settlement

Epochs follow `(timestamp − genesis) / epochDuration`; the deployment default is 86,400 seconds. Fee recording and burning follow this calendar even if no keeper runs. `closeEpochs` closes at most 64 epochs per call. Votes during epoch N determine epoch N+1; epoch N keeps its existing asset.

| State | Meaning and transition |
| --- | --- |
| Open | The initialized calendar epoch is collecting fees and votes. |
| Pending | A closed epoch has TOKEN and/or USDG fees and awaits settlement. Failed execution leaves it here for retry. |
| Empty | A closed epoch has neither fee currency; no purchase is attempted. |
| NoStake | A funded epoch had zero historical stake-seconds. Capital stays reserved; later staking cannot claim it. |
| Settled | The original asset was purchased and actual ERC-20 units funded staking. A second settlement is rejected. |

`settleEpoch(epoch, normalizationMinOut, stockMinOut, deadline)` first checks the historical staking denominator. It then normalizes that epoch's TOKEN fees, releases its USDG to the fixed controller, purchases its fixed Stock Token, and funds staking. An external self-call provides a rollback boundary: any failure in normalization, execution, token transfer, or reward funding undoes all movements in that attempt. No substitute Stock Token is selected. The outer call returns `false` and emits `EpochPending`; a successful transaction alone does not prove purchase success.

Each record retains start, end, asset, accumulated/deployed USDG, raw Stock Tokens received, settlement timestamp, and status. Newer epochs can settle before an older pending epoch. When normalization uses the launch pool, it creates a new current-epoch USDG reward fee. Both adapter and vault subtract that separately recorded fee from the closed epoch's received-output calculation, preventing double credit and an inflated minimum-output check.

Zero-stake epoch capital and distribution rounding dust have no discretionary withdrawal or redistribution route. A market restriction can leave an obligation pending indefinitely.

## Staking: who earns a delayed purchase

Stake and withdrawal create timestamped cumulative balance checkpoints. A binary search recovers each user's balance integral at the original epoch boundaries, regardless of when the purchase eventually executes.

```
userWeight = integral(user, epochEnd) − integral(user, epochStart)
totalWeight = integral(totalStake, epochEnd) − integral(totalStake, epochStart)
rewardPerStakeSecond = floor(actualStockUnitsReceived × 10^36 / totalWeight)
userReward = floor(userWeight × rewardPerStakeSecond / 10^36)
```

This divides cumulative stake-time across the whole epoch. It does not integrate a user's instantaneous percentage of the staking pool. For example, if Alice stakes 100 TOKEN for 24 hours and Bob stakes 100 TOKEN for one hour, their weights are 2,400 and 100 TOKEN-hours. Before rounding, they earn 96% and 4%. Staking at the exact end has zero preceding-epoch weight. Withdrawing before a delayed settlement does not erase historical entitlement.

Stake/withdraw never iterate through every staker or through pending epochs. `claimEpochs` accepts at most 64 epoch IDs. `claimAsset` advances through up to 64 funded epochs for one asset; `claim` and `claimAll` process one such page for each known reward asset, with at most 32 assets. Use smaller explicit batches for tighter gas bounds. `earnedPage` supports bounded reads; `earned` is a convenience view over the full asset history. Out-of-order settlement appends to the claimable history, and unfunded epochs are never marked claimed.

Eligibility is checked before claims transfer Stock Tokens. Ineligible balances remain attributed to their owners. `withdraw` remains available independently of eligibility; `exit` withdraws TOKEN and only attempts rewards when eligible. NVDA, TSLA, and AAPL balances remain separate. Fee-on-transfer and rebasing stake/reward assets are outside the supported accounting assumptions.

## Permanent-burn voting

`burnFor(asset, amount)` calls TOKEN's allowance-based `burnFrom` and records the actual permanent burn in the calendar epoch. The approved-asset list is add-only, with at most 32 choices. Highest total burns wins. If the incumbent is tied for first, it stays; otherwise the lowest numerical asset address among tied leaders wins. No votes retain the incumbent. Completed results cannot change, votes cannot be backdated, and burns are not refundable.

Asset approval is a governance responsibility. A working approved route, matching canonical metadata, and appropriate eligibility must be established before adding a choice. Permanently approving an unusable asset can strand future obligations.

## Stock Token execution and corporate actions

The production adapter has fixed TOKEN/USDG and one-time controller/vault wiring. An owner schedules a complete route configuration; anyone can execute it after the immutable route delay, which must be at least one hour. Each route fixes an executor, input/output feeds, separate maximum ages, slippage cap, enabled flag, UID, and capability-metadata hash. Runtime executor code hashes are checked. The maximum configurable slippage is 1,000 basis points; this 10% hard ceiling is not a recommended trading tolerance.

Input and output are valued independently through USD feeds with normalized decimals. The adapter takes the stricter of the keeper's positive minimum and the upward-rounded oracle floor. Feed answers must be positive, completed, nonzero-timestamped, not future-dated, and fresh under the configured ages. Stock Token `oraclePaused()` and configured sequencer downtime/recovery checks can defer settlement. A deadline must be no later than 30 minutes ahead. Actual input consumption and net recipient output are measured, and allowances are cleared.

`V4RouteExecutor` supports one to three immutable hops and only fully filled exact-input execution. Any insufficient-liquidity or minimum-output failure rolls back the complete route. There is no caller-selected router, arbitrary calldata, or runtime HTTP request. Capability metadata describes an asset; it does not enforce every trading restriction onchain. Production venue and eligibility integrations must supply the applicable controls.

Accounting always distributes raw ERC-20 units actually received. `economicUnits(stock, rawUnits)` applies `uiMultiplier()` only for human-readable quantities. The documented canonical Stock Token feed already reflects the corporate-action multiplier: multiplying its price again would double-count that adjustment. Route authenticity depends on validated canonical identity and governance, not on a token merely implementing `uid()`.

## Protocol liquidity and management limits

Small active two-sided liquidity opens trading. TOKEN-only ranges on the rising economic price side progressively become active and exchange protocol TOKEN inventory for USDG. When TOKEN is currency0, higher economic prices mean higher ticks; when TOKEN is currency1, they mean lower ticks. With 18-decimal TOKEN and 6-decimal USDG, the opening raw TOKEN0 price is `3 × 10^-18`. `BootstrapCurve` uses upstream integer tick and liquidity math.

LiquidityManager owns native v4 positions with unique salts. Funding is irrevocable, `sealBootstrap` is permanent, and there is no founder withdrawal, sweep, or arbitrary recipient function. Repositioning removes one complete position into the manager, then creates its replacement using available balances; idle inventory can be consumed, while other positions stay intact.

Configuration, reposition, and emergency roles can migrate through delayed nomination and acceptance. Repositioning waits at least 24 hours and expires 24 hours after becoming ready. Queue and execution both require a live two-sided range, each boundary at least one tick spacing and within the immutable distance limit from spot. The constructor ceiling is 20,000 ticks; the demo uses 10,000. The emergency role can pause management or cancel actions, not withdraw positions. Trading itself remains live.

These bounds prevent direct extraction but do not prove preservation of economic value. Spot can be manipulated, and governance can choose poor permitted ranges. Production still needs manipulation-resistant reference checks, strategy-specific value-loss limits, and reviewed governance operations. `positionInventory` excludes uncollected LP fees; cumulative deposits/redemptions are gross movements, not profit.

## Canonical configuration and launch readiness

Explicit chain IDs are LOCAL 31337, ROBINHOOD_TESTNET 46630, and ROBINHOOD_MAINNET 4663. RPC endpoints come from named environment variables. Official source snapshots bind the configured mainnet PoolManager, USDG, NVDA/TSLA/AAPL addresses, UIDs, and price-feed metadata. The mainnet manifest records a September 11, 2026 read-only code/UID/decimal verification, but `broadcastEnabled` is false and every Stock Token route is disabled. Canonical asset addresses are not deployed launch-contract addresses.

The test deployment script uses mock assets and its own clearly labeled PoolManager. It rejects mainnet by network name or chain ID before broadcast setup. The existing evidence records 67 passing Solidity tests, 15 Python tests, two 256-case fuzz tests, format/configuration checks, a full local dry-run, and a Robinhood testnet fork dry-run. No testnet transactions were broadcast; no mined launch addresses or deployed-service claims follow from those simulations.

Before a production launch: implement and validate eligibility/transfer controls; verify a sequencer uptime feed; vet funded execution routes; provide an independent TOKEN normalization reference oracle; add LP strategy value-loss protection; finalize multisig/timelock roles and economic parameters; obtain external security review; and complete funded testnet deployment with receipts and end-to-end claim tests. Reverify canonical configuration against its official sources before deployment. No mainnet enablement is provided by this build.

Source records: `src/*.sol`, `src/libraries/*.sol`, `docs/rewards.md`, `docs/hook-liquidity.md`, `docs/production-routing.md`, `SECURITY.md`, `config/ROBINHOOD_MAINNET.json`, `config/dependencies.lock.json`, and `reports/verification.md`.
