Security model
What is immutable, what an admin can still touch, and the risks we will not paper over.
This page is the uncomfortable one on purpose. Below is what the contracts guarantee, what an administrator can still reach, and which trade-offs we made knowingly. If something here changes, this page changes with it.
#What is genuinely immutable
| Guarantee | Why it holds |
|---|---|
| A launch position can never be unlocked | The FeeLocker exposes no transfer, approve, decreaseLiquidity, burn or sweep path for a held NFT — not to the owner, not to anyone. Only collect() exists. |
| Token supply can never grow | HoodToken mints once in its constructor and has no mint function. It is not a proxy. |
| Your fee split is fixed at launch | creatorBps is written into the position at deposit and there is no setter for it anywhere. |
| Your fee policy is fixed at launch | A token binds to a module contract, not a policy id. Re-pointing an id affects future launches only. |
| A dexId can never be re-pointed | addAdapter reverts if the id is bound. The only mutable registry bit is a pause, which can gate but never redirect. |
| A venueId can never be re-pointed | Same append-only rule on the launcher’s venue registry. |
| Fee caps cannot be exceeded | MAX_PLATFORM_FEE_BPS (2%), MAX_REFERRAL_BPS (50% of the fee), MAX_LAUNCH_FEE (1 ETH) and MIN_CREATOR_BPS (10%) are constants in the deployed bytecode; a setter that would breach one reverts. |
| Referral balances cannot be seized | ReferralManager has no ETH rescue path. Every wei in it is owed to a referrer. |
#The admin surface
Everything an owner can do. If it is not on this list, no privileged party can do it.
| Contract | Can | Applies to |
|---|---|---|
| HoodLauncher | Set the launch fee, the protocol-wide creator split, sniper-guard defaults, supply and FDV bounds; append a venue; re-point the registry and fee managers. | Future launches only |
| FeeLocker | setFeeReceiver — change what happens to collected fees. Renouncing ossifies it. | Future collections |
| FeePolicyManager ×2 | setModule(id, module) and setLauncher. | Future launches only |
| StakingFeeModule | setPoolImplementation — the master copy future pools clone. | Future pools only |
| TokenOwnerRegistry | setLauncher only. It cannot read, write or transfer any token’s ownership. | Future launches only |
| V4TradeManager | Add an adapter, pause a dexId, set the fee (≤2%), the referral share (≤50% of the fee), the fee receiver, the referral manager and the tracker hook. | Live trades |
| ReferralManager | Authorise/de-authorise trade managers; rescue stray ERC-20s. | Live |
| CashBackFeeReceiver | Owner: set the default cash-back rate (≤90%), per-wallet rates, and who may claim on a user’s behalf. Treasury: withdraw the protocol’s share, capped at freeBalance() — balance minus every trader’s unclaimed cash back — and rotate itself. Neither can touch an accrued balance or a user’s payout asset. | Future trades; accrued balances are untouchable |
| V3FeeReceiver | Nothing. No owner. The protocol recipient can only rotate itself. | — |
| HoodToken · HoodLocker · HoodAirdrop · TokenStakingPool · BuyBurn · Burn modules | Nothing. These contracts have no owner at all. | — |
The two settings that affect live state rather than future launches are the trading fee and the referral share, both hard-capped, and the per-dexId pause, which can only disable a venue. Everything else is forward-looking by construction.
Worth stating the bound plainly: the widest reach any of these settings has is to raise the trading fee as far as 2%, redirect future fee revenue, pause a venue, and change the terms of launches that have not happened yet. None of them can unlock an LP position, mint a token, take a balance, change a launched token’s fee split or policy, re-point an existing dexId, or touch anyone’s referral, staking or cash-back balance — because no contract in the system implements those functions.
#How the contracts are tested
- Full unit-test suites per contract, including adversarial mocks — reverting fee modules, blocklisting tokens, fee-on-transfer tokens, reentrancy attackers, and pools that starve a mid-route hop.
- Fork tests against the real on-chain periphery: single-sided boundary-tick mints in both token orderings, a real router dev buy, launch → swaps → collect → split end-to-end, and live round-trips through the V4 adapters against real hooked pools.
- Post-deploy wiring scripts that re-verify every pointer between contracts on mainnet, and full Blockscout verification — so what is running is readable by anyone, not just described by us.
#Known trade-offs
Each of these is a decision, not an oversight. Here is the reasoning for each.
#The 90-day public buyback
Anyone can trigger an abandoned token’s buy-and-burn after 90 days of inactivity, and that caller picks their own minTokensOut — so they could sandwich their own call. We took that over accrued ETH being stuck forever when a team walks away. The full-balance rule stops dust calls from resetting the clock while leaving the pot hostage.
#The V4 hook allowlist is off-chain
The multi-hop adapter accepts any hook in a pool key; the route finder enforces the allowlist and minAmountOut is the economic backstop. Encoding an allowlist on-chain would mean a new adapter for every new hook. If you build your own routes against the adapter, the hook check is yours to make.
#Referral attribution trusts the caller
The contract pays whoever is named as ref on a trade. Eligibility rules live off-chain because encoding them would mean redeploying the trade manager to change one. Payouts are single-level and capped at 50% of the fee, so the blast radius of a bad ref is one trade’s fee share.
#Third-party pools can be hostile
The terminal routes to any venue on the chain, including pools with fees far above 1% and pools with almost no liquidity. That is deliberate — refusing to route is not the same as protecting you, and blocking a pool just moves the trade somewhere with worse execution. Instead, the app surfaces the pool fee and a low-liquidity warning before you confirm, and prices routes net of fees. Read the confirmation.
#A backing vault’s floor is not a ratchet
The FLOOR policy divides a vault’s ETH by the supply that can actually redeem it, which means a buy lowers the per-token floor — it unlocks supply from the launch position, so the same ETH covers more claimants. Sells, burns, fee accruals and redemptions raise it. We chose the honest denominator over a number that only goes up, and the UI is written to say so. Full mechanics: Fee policies.
#Block-number semantics
Solidity’s block.number tracks the parent chain here, so every block-counted window in these contracts is measured in ~12-second blocks. It is documented on Robinhood Chain because it is the single easiest thing to get 120× wrong when integrating, and no local test will catch it.
#Reporting something
If you find a vulnerability, please report it privately first — reach us on X and we will get you a direct channel. Do not test findings against live user funds; a mainnet fork reproduces this system faithfully, including the real periphery, and is the right place to demonstrate an issue.
