# cANDLE · The Living Candle Chart of the Onchain Stock Market

**Version 1.0 · Litepaper / Whitepaper**
**Network** : Robinhood Chain (Ethereum L2, Arbitrum stack)
**Standard** : ERC-20 + Uniswap V4 Hook + ERC-721 (singleton)
**Status** : pre-deployment (audit pending)

---

## Table of contents

1. Abstract
2. Motivation and prior art
3. Mathematical encoding of candles
4. The Uniswap V4 hook contract
5. The on-chain SVG renderer
6. The Harberger ownership mechanism
7. Economic analysis of the equilibrium
8. Tokenomics and initial distribution
9. Liquidity, fees, and value redirection
10. Security model and threat analysis
11. Gas economics
12. Deployment, governance, and end-state
13. Future extensions
14. Glossary and references

---

## 1. Abstract

cANDLE is an experimental on-chain artifact built on Robinhood Chain, the Ethereum L2 where tokenized equities trade 24/7, that fuses three primitives, an ERC-20 token, a Uniswap V4 swap hook, and a singular ERC-721 NFT, into a single self-contained system. The token's pool activity drives the visual state of one perpetually mutating NFT, called *The Wick*. The Wick is held by a single address at any time and is permanently for sale through a continuous Harberger tax mechanism, denominated in USDG. Every swap of cANDLE prints a trace inside a 32-slot circular buffer. The on-chain SVG renderer reads the buffer and produces a living candle chart of the pool's recent life. On a chain where the market never closes, the candles never stop printing, unless the community lets it halt.

This document specifies the construction in mathematical and engineering detail.

---

## 2. Motivation and prior art

### 2.1 The "frozen" meta

A family of on-chain objects emerged on Ethereum mainnet, exemplified by Unipeg ($UPEG). These objects are token-as-artwork hybrids. The artwork is captured by a Uniswap V4 hook at a specific moment and frozen on-chain forever. The frozen-artifact thesis is psychologically powerful : permanence is a classical value driver in collectibles. But it is also a one-shot. Once the moment is captured, the artifact is no longer a function of the market.

### 2.2 The "dynamic" counter-thesis

wAVE inverted the time axis on Ethereum mainnet : instead of a frozen birth, a heartbeat. Its artifact, *The Tide*, is a function of the most recent thirty-two units of pool activity, drawn live by an `afterSwap` hook and custodied by Harberger taxation. wAVE proved that a living, self-drawing artifact with cycling ownership is a coherent economic object.

### 2.3 The candle thesis

cANDLE ports the living-artifact thesis to the venue where it means the most. In July 2026, Robinhood Chain launched : an L2 where equities exist as tokens, markets run 24/7, and Uniswap V4 is native from day one. The oldest visual language in markets, **the candle**, green when buyers win, red when sellers win, invented by Japanese rice traders three centuries before Wall Street, can now exist literally, as a living contract. Every swap is a candle. Every candle prints to *The Wick*. The artifact is not "about" the market ; it *is* the trace of the market's own life, block by 250-millisecond block.

The lineage : uPEG froze the moment. wAVE captured the heartbeat. cANDLE lights the chart.

### 2.4 Harberger ownership

The classical problem with a perpetually mutating singular artifact is *who owns it*. A dynamic NFT held forever is unfair : the holder benefits indefinitely from the activity of others without anyone being able to capture the position. The solution adopted here is Harberger taxation, originally proposed by Posner and Weyl in *Radical Markets* (2018). The current holder posts a self-assessed price ; anyone can buy at that price at any time ; the holder pays a continuous tax proportional to the posted price. Holding a desirable asset becomes expensive in proportion to its desirability, and ownership cycles automatically.

### 2.5 Related implementations

- *This Artwork is Always On Sale* (Simon de la Rouviere, 2019) demonstrated Harberger NFT ownership on Ethereum with a single static image.
- *PunkStrategy* (2025) implemented a perpetual purchase machine for CryptoPunks, validating protocol-driven collecting loops.
- *wAVE* (2026) combined a V4 swap hook, a continuously mutating on-chain SVG, and Harberger custody on a singular artifact on Ethereum mainnet, the direct predecessor in spirit and mechanism.

cANDLE is the first construction known to the authors that brings this class of object to a chain whose economic substrate is the tokenized stock market itself, with dollar-denominated (USDG) Harberger custody.

---

## 3. Mathematical encoding of candles

### 3.1 The Candle struct

A single candle occupies sixteen bytes :

```
struct Candle {
    int88   amount;       // signed amount0 delta of all swaps in this block
    uint32  blockDelta;   // blocks elapsed since previous candle entry
    uint8   flags;        // bit 0: net direction, bits 1..3: log magnitude bucket
                          // bits 4..7: reserved
}
```

Two candles fit in one EVM storage slot (32 bytes), so the full 32-entry buffer occupies sixteen slots.

### 3.2 Sampling rule

Let `B(s)` denote the block number of swap `s`. Let `H` denote the storage cell `head` (an index in `{0, ..., 31}`). Let `last` denote `lastBlock`.

- If `B(s) = last`, swap `s` is *aggregated* into `buffer[H]`. No new entry is created.
- If `B(s) > last`, the head advances : `H ← (H + 1) mod 32`. A new candle is written at `buffer[H]` and `last ← B(s)`.

This rule guarantees at most one new entry per block and is the system's primary anti-spam defense. On Robinhood Chain the rule bites harder than on mainnet : with ~250 ms blocks, a bot spamming swaps still cannot advance the buffer faster than four entries per second, and the 1 % fee tier (§ 8.5) makes doing so expensive. An adversary cannot cheaply pollute the visual.

### 3.3 Signed amount encoding

Let `Δ` be the signed amount0 delta of a swap (positive when cANDLE leaves the pool, ie a buy ; negative when cANDLE enters the pool, ie a sell).

For aggregation in the same block we compute :

```
amount_new = sat( amount_old + Δ , INT88_MIN, INT88_MAX )
```

where `sat(x, a, b)` clamps `x` to `[a, b]`. This ensures the visual stays bounded even during a coordinated burst.

### 3.4 Log-bucket magnitude

The visual uses the magnitude bucket from `flags` rather than the raw `amount`, to prevent a single mega-swap from making all other candles look like flat lines.

Define :

```
bucket(amount) = floor( log2( max(|amount|, 1) ) )
              clamped to {0, ..., 7}
```

This produces eight buckets, mapped to bar heights `h_b ∈ [10, 280]` pixels :

```
h_b = 10 + b · 270 / 7        (b = 0, 1, ..., 7)
```

| Bucket | Magnitude range (token wei)    | Bar height (px) |
|-------:|--------------------------------|----------------:|
| 0      | 1 to 1                          | 10              |
| 1      | 2 to 3                          | 49              |
| 2      | 4 to 7                          | 87              |
| 3      | 8 to 15                         | 126             |
| 4      | 16 to 31                        | 164             |
| 5      | 32 to 63                        | 203             |
| 6      | 64 to 127                       | 241             |
| 7      | 128 to ∞                        | 280             |

(Magnitude is computed against the actual token decimals, values shown in raw wei for illustration.)

### 3.5 Direction flag

```
direction = sign(amount)        ∈ {+1, 0, -1}
flags.bit0 = (direction == +1 ? 1 : 0)
```

A neutral candle (perfectly cancelled aggregation) is rendered as a flat print. Up-prints render in market green ; down-prints render in market red, the visual grammar every retail trader already reads.

### 3.6 Time decay

When the renderer receives the buffer, each candle at offset `i` from the head (where `i = 0` is the most recent and `i = 31` is the oldest) is rendered with opacity :

```
α_i = (32 - i) / 32
```

The oldest candle has α = 1/32 ≈ 3 %. This produces the visual sense of *fading memory*, encoding the buffer's circular nature directly into the image, the chart scrolls off into the past.

### 3.7 Halt state

Let `Δ_block = block.number - last` be the block gap since the most recent candle.

Define a halt threshold `T_h = 345 600` blocks (≈ 24 hours on Robinhood Chain at ~250 ms blocks).

If `Δ_block > T_h`, the renderer overlays :
- A semi-transparent gray layer (opacity 0.6).
- A `feTurbulence` filter producing static-noise grain.
- Two diagonal "crack" polylines.
- The legend **THE WICK IS OUT** across the center line.

The halt state is the strongest possible coordination signal on a chain whose entire identity is *markets that never close*. It is reversible : as soon as a swap occurs, `last` updates and the halt overlay disappears at the next read of `tokenURI`.

---

## 4. The Uniswap V4 hook contract

### 4.1 Permissions

```solidity
function getHookPermissions() external pure returns (Permissions memory) {
    return Permissions({
        beforeInitialize:        false,
        afterInitialize:         false,
        beforeAddLiquidity:      false,
        afterAddLiquidity:       false,
        beforeRemoveLiquidity:   false,
        afterRemoveLiquidity:    false,
        beforeSwap:              false,
        afterSwap:               true,
        beforeDonate:            false,
        afterDonate:             false,
        beforeSwapReturnDelta:   false,
        afterSwapReturnDelta:    false,
        afterAddLiquidityReturnDelta:    false,
        afterRemoveLiquidityReturnDelta: false
    });
}
```

The permissions byte is `0x0040`. The hook contract address must be mined to encode this byte in its low bits, per the V4 hook deployment specification. The procedure (CREATE2 salt grinding) is identical on Robinhood Chain, which runs the canonical V4 core.

### 4.2 afterSwap implementation

```solidity
function afterSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    BalanceDelta delta,
    bytes calldata hookData
) external override returns (bytes4, int128) {
    int128 amount0 = delta.amount0();
    int88 packed = _saturate88(amount0);

    uint32 currentBlock = uint32(block.number);
    if (currentBlock == lastBlock) {
        Candle storage cur = buffer[head];
        cur.amount = _satAdd(cur.amount, packed);
        cur.flags = _flagsFor(cur.amount);
    } else {
        unchecked { head = (head + 1) & 31; }
        uint32 gap = currentBlock - lastBlock;
        buffer[head] = Candle({
            amount: packed,
            blockDelta: gap,
            flags: _flagsFor(packed)
        });
        lastBlock = currentBlock;
        lastSwapTs = uint32(block.timestamp);
    }

    return (BaseHook.afterSwap.selector, 0);
}
```

### 4.3 Storage layout (gas-critical)

| Slot   | Content                                                  |
|--------|----------------------------------------------------------|
| 0      | head (uint8) ∥ lastBlock (uint32) ∥ lastSwapTs (uint32) ∥ padding |
| 1..16  | Candle[32] (two candles per slot)                            |

This packing gives a worst-case afterSwap gas cost of one SSTORE on slot 0 (already warm because we update `lastBlock`) plus one SSTORE on the relevant Candle slot. The intra-block aggregation case rewrites a hot slot ; the new-block case writes a cold slot in the buffer plus the warm head/lastBlock slot.

### 4.4 Gas budget

| Path                              | Estimated gas |
|-----------------------------------|--------------:|
| Same-block aggregation (hot)      | ~ 8 000       |
| New block, cold buffer slot       | ~ 22 000      |
| Wraparound (head transitions 31→0)| ~ 22 000      |

On Robinhood Chain, L2 execution gas is priced in fractions of a cent, so the hook overhead is economically invisible to the swapper. The budget discipline is kept anyway : the hook must never be the reason a swap fails, and gas-efficiency guarantees survive any future fee-market regime on the chain.

---

## 5. The on-chain SVG renderer

### 5.1 Interface

```solidity
function render(
    Candle[32] memory candles,
    uint8 head,
    uint32 lastBlock,
    uint32 currentBlock,
    bytes3[5] memory palette
) external pure returns (string memory svg);
```

### 5.2 Coordinate system

The viewBox is `0 0 1000 600`. The 32 columns are placed at :

```
x_i = 15 + i · 31.25         (i = 0..31)
column width = 28
center_y = 300
```

For each column representing a candle at offset `o` from the head (oldest first → newest last) :

```
o = (32 + i - (head + 1)) mod 32
h = h_bucket( candle[o].flags )
direction = (candle[o].flags & 1) ? +1 : -1
y_top = 300 - h    if direction == +1
y_bot = 300       (always anchored to center)
```

### 5.3 Bezier connector

Adjacent column tips are connected by a smooth curve. Let `(x_i, y_i)` be the tip of column `i`. The smoothing uses C-curve control points :

```
M x_0 y_0
C x_0 + dx, y_0,  x_1 - dx, y_1,  x_1, y_1
... etc
```

with `dx = (x_{i+1} - x_i) / 3`. This produces the chart's continuous silhouette.

### 5.4 Halt overlay

Activated when `currentBlock - lastBlock > 345 600`. Adds :

```svg
<rect width="1000" height="600" fill="palette[4]" opacity="0.6"/>
<filter id="grain"><feTurbulence baseFrequency="0.9"/></filter>
<rect width="1000" height="600" filter="url(#grain)" opacity="0.15"/>
<polyline points="..." stroke="..." stroke-width="2"/> <!-- crack 1 -->
<polyline points="..." stroke="..." stroke-width="2"/> <!-- crack 2 -->
<text>THE WICK IS OUT</text>
```

### 5.5 Palette

A `bytes3[5]` array specifies five RGB colors :

| Index | Role                                  |
|-------|----------------------------------------|
| 0     | Background gradient stop A             |
| 1     | Background gradient stop B             |
| 2     | Bar fill, up-print (buy)              |
| 3     | Bar fill, down-print (sell)           |
| 4     | Halt overlay tint                      |

The current holder of the NFT may set the palette via `setPalette(bytes3[5] colors)`. The default palette is :

```
[0]  #E9FBEE    (paper green-white)
[1]  #F4FEF6    (lifted paper)
[2]  #0B8A00    (market green, buy)
[3]  #E05C5C    (market red, sell)
[4]  #8FBFA0    (halt tint)
```

---

## 6. The Harberger ownership mechanism

All prices, taxes and deposits are denominated in **USDG**, the dollar stablecoin native to Robinhood Chain. Dollar denomination is deliberate : the chain's audience thinks in dollars, and a posted price of "12,500 USDG" reads like a stock quote, not a crypto curiosity.

### 6.1 State

```solidity
WickNFT  public immutable nft;
IERC20   public immutable usdg;
address  public holder;
uint256  public price;
uint256  public taxBalance;
uint256  public lastSettleTime;

uint256 public constant TAX_RATE_BPS = 1000;   // 10 % per annum
uint256 public constant YEAR         = 365 days;
uint256 public constant MIN_PRICE    = 10e6;   // 10 USDG (6 decimals)
uint256 public constant MIN_DEPOSIT_FRACTION = 12; // ~ 1 month of tax
```

### 6.2 Tax accrual

Tax is accrued continuously at rate `r = 10 % / year`. Over an interval `Δt`, the tax due is :

```
T(Δt) = price · r · Δt / YEAR
      = price · TAX_RATE_BPS / 10000 · Δt / YEAR
```

This is integrated lazily : settlement happens on every interaction (`buy`, `updatePrice`, `depositTax`, etc.) and on view via `taxDue()`.

### 6.3 Settlement

```solidity
function _settle() internal {
    if (holder == address(0)) return;
    uint256 dt  = block.timestamp - lastSettleTime;
    uint256 due = (price * TAX_RATE_BPS * dt) / (10000 * YEAR);
    if (due >= taxBalance) {
        uint256 collected = taxBalance;
        taxBalance = 0;
        _foreclose();
        if (collected > 0) { usdg.approve(address(distributor), collected); distributor.distribute(collected); }
    } else {
        taxBalance -= due;
        if (due > 0) { usdg.approve(address(distributor), due); distributor.distribute(due); }
    }
    lastSettleTime = block.timestamp;
}
```

### 6.4 Buy

```solidity
function buy(uint256 newPrice, uint256 usdgAmount) external {
    _settle();
    require(holder != address(0), "foreclosed; use claim()");
    require(newPrice >= MIN_PRICE, "price too low");
    uint256 minDeposit = (newPrice * TAX_RATE_BPS) / (10000 * MIN_DEPOSIT_FRACTION);
    require(usdgAmount >= price + minDeposit, "insufficient");
    usdg.transferFrom(msg.sender, address(this), usdgAmount);

    address prev      = holder;
    uint256 prevPrice = price;
    uint256 refund    = taxBalance;

    holder         = msg.sender;
    price          = newPrice;
    taxBalance     = usdgAmount - prevPrice;
    lastSettleTime = block.timestamp;

    nft.transferFromHarberger(prev, msg.sender);
    usdg.transfer(prev, prevPrice + refund);
}
```

Using an ERC-20 (rather than native value) removes the re-entrancy surface of a native-value refund call : USDG performs no receiver callback.

### 6.5 Foreclosure

When `taxBalance` reaches zero, ownership reverts to the `HarbergerManager` itself with `holder = address(0)` and `price = MIN_PRICE`. Anyone may then call `claim(uint256 newPrice, uint256 usdgAmount)` to take over at any price ≥ `MIN_PRICE`.

### 6.6 Properties

The mechanism guarantees :

- **Always for sale.** There exists no path through which `buy()` can revert when the caller supplies `price + minDeposit` in USDG and `holder ≠ address(0)`.
- **No double-spend of tax.** `_settle()` is monotonically additive on `lastSettleTime` ; revisiting an already-settled interval is impossible.
- **Foreclosure is never silent.** Foreclosure transitions emit `Foreclosed(address oldHolder, uint256 priceAtForeclosure)`. Front-ends and indexers must subscribe to this event.

### 6.7 Edge cases

| Scenario                              | Behavior                                                          |
|---------------------------------------|-------------------------------------------------------------------|
| Holder posts price = 0                | Reverts (require ≥ MIN_PRICE).                                    |
| Holder posts price = 2^256 − 1        | Tax overflows the deposit instantly ; `_settle` triggers foreclose. |
| Buyer front-runs holder's price update| Atomic ; the price read at the start of the buy tx is the price paid. |
| Holder withdraws all tax then leaves  | Allowed via `withdrawExcessTax` only if `taxBalance > minDeposit`. |
| Malicious ERC-20 callback             | None : USDG is a plain ERC-20 without hooks.                      |

---

## 7. Economic analysis of the equilibrium

### 7.1 Holder optimization problem

Let `v` be the private valuation of a holder for The Wick (USDG). Let `p` be the posted price. The holder solves :

```
max  v · 1[no buyout] − r · p · t − (p − v) · 1[buyout]
 p, t

subject to:  buyout occurs whenever an outsider has v' > p.
```

The literature shows that under common-prior valuations and small transaction costs the optimal posted price converges on the holder's true valuation. In practice, holders post slightly above or below depending on attention they wish to attract.

### 7.2 Long-run holding cost

If a holder retains The Wick for time `t` (years) at posted price `p`, the cumulative cost is :

```
C(t, p) = r · p · t + (p − v_buy) · 1[sold]
        = 0.10 · p · t + (p − v_buy) if eventually sold.
```

For example, holding at p = 25,000 USDG for one year costs 2,500 USDG in tax, about 6.85 USDG per day. Dollar denomination makes the carry cost legible to anyone who has ever paid a subscription.

### 7.3 Closed-loop reinforcement

The system has a positive-feedback loop whose strength depends on the share of tax redirected to LPs. Let `f_LP = 0.7` (the share of tax sent to `PoolManager.donate`). Let `Q` be the trading volume per period and `π = 0.01` the swap fee. Then the LP revenue per period is :

```
R_LP = π · Q + f_LP · r · p · Δt / YEAR
```

Higher `R_LP` attracts more LP capital `L`, which lowers price impact, which raises `Q`, which raises `R_LP`. The fixed point depends on demand elasticity and the holder's price. The mechanism is thus a coupled oscillator between trading activity and Harberger valuation.

### 7.4 Halt-state forcing function

When `Δblock > 345 600`, the visual deteriorates into THE WICK IS OUT. This is a *coordination signal* : holders of cANDLE who do not own The Wick still benefit from The Wick being alive (it drives demand for cANDLE). On a chain whose entire brand is 24/7 markets, an extinguished wick is maximally dissonant, anyone in the community has a direct incentive to swap, even at a loss, to prevent it. A small swap costs cents on Robinhood Chain and resets the halt timer : the public-goods problem is converted into a tragedy-resistant one.

### 7.5 Snapshot economics (phase 2)

The future `SnapshotMinter` lets anyone mint a new ERC-721 that captures the current buffer state, a *print* of a memorable session, paying a fee `s`. The fee splits 50/50 between the current holder and the treasury. Let `n` be the snapshot rate per period. The current holder earns :

```
H_revenue = 0.5 · n · s
```

This stream of income directly subsidizes the holder's tax bill, making high posted prices economically rational and stabilizing high-value tenures.

---

## 8. Tokenomics and initial distribution

### 8.1 Supply

- Total supply : **1 000 000 000** cANDLE
- Decimals : 18
- Mint / burn : initial mint to deployer, no further mint authority. Burn function callable by anyone (used by buyback).

### 8.2 Allocation

| Allocation                | %    | Tokens           | Vesting / Lock                              |
|---------------------------|-----:|------------------|---------------------------------------------|
| Liquidity Pool (V4)       | 70 % | 700 000 000      | LP NFT burned at deploy → permanent lock   |
| Treasury (multisig 3-of-5)| 15 % | 150 000 000      | No vesting ; spend transparently           |
| Team                      | 10 % | 100 000 000      | 12-month linear vest, 3-month cliff        |
| Community Airdrop         |  5 % |  50 000 000      | Merkle-claim, 30-day window                |

### 8.3 Pool configuration

| Parameter       | Value                                          |
|-----------------|------------------------------------------------|
| Pair            | cANDLE / USDG                                    |
| Fee tier        | 1 % (10 000 bps)                               |
| Tick spacing    | 200                                            |
| Hook            | `CandleHook` deployed at mined address           |
| Initial price   | calibrated to FDV target (deployment parameter) |

### 8.4 Liquidity model

The 70 % LP allocation is paired with the corresponding USDG reserve (provided by deployment treasury) to seed the pool. The LP NFT is burned immediately, removing all rug-pull surface. The pool is permissioned by code only ; nobody, including the deployer, can withdraw the initial liquidity.

### 8.5 Why a 1 % fee tier

On an L2 where gas costs fractions of a cent, fee friction is the *only* spam filter. Lower fee tiers (0.05 %, 0.3 %) encourage micro-arbitrage and high-frequency MEV. We *do not want* this : every swap prints a candle and we want candles to represent meaningful activity. A 1 % fee tier filters out noise and ensures each print reflects a deliberate trade. It also boosts LP revenue, supporting the LP-donate distribution loop in § 9.2.

---

## 9. Liquidity, fees, and value redirection

### 9.1 Two revenue streams to the system

The cANDLE ecosystem has two independent revenue streams :

1. **Swap fees** (1 % of every trade), accrue to LPs natively per V4.
2. **Harberger tax** (10 %/year on the posted price of The Wick, in USDG), collected by `HarbergerManager` and routed by `TaxDistributor`.

### 9.2 TaxDistributor split

```
70 % → PoolManager.donate(poolKey, 0, taxAmount)   // USDG side donated to in-range LPs
20 % → swap USDG for cANDLE then burn                // deflationary
10 % → treasury multisig                           // operations
```

### 9.3 Buyback-and-burn detail

```solidity
function _buybackAndBurn(uint256 usdgAmount) internal {
    if (usdgAmount == 0) return;
    PoolSwapParams memory p = PoolSwapParams({
        zeroForOne: false,             // USDG → cANDLE
        amountSpecified: -int256(usdgAmount),
        sqrtPriceLimitX96: TickMath.MAX_SQRT_RATIO - 1
    });
    BalanceDelta delta = poolManager.swap(poolKey, p, "");
    uint256 candleBought = uint256(int256(delta.amount0()));
    cANDLE.burn(candleBought);
}
```

This is a perpetual deflationary pressure on the token, proportional to the desirability of The Wick. Note the pleasing symmetry : the buyback itself is a swap, so *paying the tax prints a candle*.

### 9.4 Treasury constraints

The treasury multisig (3 of 5) is bound by a public charter (publishable as a signed document at deploy) :

- Treasury funds may only be spent on : audits, infrastructure (RPC, indexer), marketing of the protocol, bug bounties, future development of related extensions (snapshot minter, market-chart hooks).
- Treasury may *not* sell the team allocation.
- Treasury may *not* withdraw LP liquidity (it cannot, LP NFT is burned).
- Treasury changes (signer rotation) require on-chain timelock of 7 days.

---

## 10. Security model and threat analysis

### 10.1 Attack surface inventory

| Surface                                | Severity if exploited           |
|----------------------------------------|---------------------------------|
| Hook gas DoS (overflow afterSwap gas)  | High, kills tradability         |
| Hook re-entrancy via ERC-20 callback   | Low, cANDLE and USDG are plain ERC-20s, no callback |
| Buffer corruption / out-of-bounds      | High, could brick rendering    |
| HarbergerManager re-entrancy on refund | Low, USDG transfer has no receiver callback |
| Foreclosure race / claim front-running | Low, first-come fair-game      |
| Integer overflow in tax accrual        | Medium, solidity 0.8 reverts   |
| Renderer producing invalid SVG         | Medium, bad tokenURI but recoverable via renderer swap |
| Initial auction griefing               | Medium, bot snipers acceptable |
| Sequencer downtime (L2-specific)       | Low, no liquidations exist ; halt timer is block-based and pauses with the chain |

### 10.2 Mitigations

- **Hook gas budget.** Continuous benchmarking : every PR must show afterSwap gas ≤ 25 000 in the hot path.
- **Re-entrancy.** Strict checks-effects-interactions in `HarbergerManager` ; ERC-20 denomination removes the native-value refund callback entirely. `ReentrancyGuard` modifier on `buy`, `claim`, `withdrawExcessTax` as belt-and-suspenders.
- **Buffer integrity.** `head` masked with `& 31` (bitwise) ; `Candle` struct fields all bounded by their types ; `int88` saturation explicit.
- **Renderer mutability window.** Owner of `WickNFT` may swap the renderer for the first 30 days post-launch then `renounceRenderer()` is called, freezing it. This window is to fix any visual bug discovered post-deploy without bricking the artifact.
- **Initial auction.** Anti-sniping rule : if a bid arrives in the last 5 minutes, the auction extends by 5 minutes. Maximum extension 24 hours.

### 10.3 Audit plan

- **Phase A** : internal review with three rounds of self-audit using Slither, Mythril, and manual fuzzing via Echidna.
- **Phase B** : external audit by one tier-1 firm with a primary scope on `CandleHook` and `HarbergerManager`.
- **Phase C** : public audit contest (Cantina or Code4rena) for two weeks before mainnet.
- **Phase D** : permanent Immunefi bug bounty post-launch. Tier sizing : critical = $50 000, high = $20 000, medium = $5 000.

### 10.4 Public testnet plan

Robinhood Chain testnet deployment minimum 14 days before mainnet. Open swap and Harberger interaction. Public faucet for test cANDLE. Indexer running publicly. All contracts identical to the mainnet build (only chain id differs).

---

## 11. Gas economics

### 11.1 Per-swap cost

Estimated added cost from `CandleHook.afterSwap` :

| Path                                   | Gas    | Approx. cost on Robinhood Chain |
|----------------------------------------|-------:|--------------------------------:|
| Same-block aggregation (warm)          |  8 000 | < $0.001                         |
| New block, cold buffer slot            | 22 000 | < $0.002                         |
| New block + wraparound                 | 22 000 | < $0.002                         |

L2 execution gas on Robinhood Chain is priced in fractions of a cent. The hook is economically invisible to the swapper ; the binding constraint on spam is the 1 % pool fee, not gas.

### 11.2 tokenURI cost

`tokenURI` is a `view` function. It executes off-chain when called by indexers and front-ends. Its on-chain measured gas (when used inside another transaction, e.g. composability) is ~ 350 000 to 500 000 depending on the buffer state. This is acceptable because the typical caller is a wallet or indexer, not a contract.

### 11.3 Harberger cost

| Action                           | Gas (estimated) | Approx. cost on Robinhood Chain |
|----------------------------------|-----------------:|--------------------------------:|
| `buy()` (new holder)             | 130 000          | < $0.01                          |
| `updatePrice()`                  |  45 000          | < $0.005                         |
| `depositTax()`                   |  55 000          | < $0.005                         |
| `withdrawExcessTax()`            |  55 000          | < $0.005                         |
| `claim()` (after foreclosure)    | 130 000          | < $0.01                          |

On mainnet, wAVE-class Harberger interactions cost $4 to $10 in gas. Here they cost less than a cent : the Harberger market can cycle at retail speed, which is precisely the point of putting the candles on Robinhood Chain.

---

## 12. Deployment, governance, and end-state

### 12.1 Deployment sequence

1. Deploy `cANDLE` ERC-20. Mint 1B to deployer.
2. Mine an address for `CandleHook` such that the address encodes `afterSwap = true` permission bit (CREATE2 salt grinding, off-chain).
3. Deploy `CandleHook` at the mined address.
4. Initialize the V4 pool with `cANDLE / USDG`, fee tier 1 %, hooks = CandleHook.
5. Deposit 70 % of supply + paired USDG into the pool. Burn the LP NFT.
6. Deploy `SVGRenderer` library.
7. Deploy `WickNFT` referencing `CandleHook` and `SVGRenderer`.
8. Deploy `TaxDistributor` referencing the V4 PoolManager and pool key.
9. Deploy `HarbergerManager` referencing `WickNFT`, `TaxDistributor`, and the USDG token.
10. Wire `WickNFT.setHarbergerManager(...)` so transfers are gated.
11. Deploy `InitialAuction` referencing `HarbergerManager`. Mint The Wick to the auction contract.
12. Distribute team and community allocations.
13. Open the auction. 24-hour duration, 5-minute extension on last-5-min bids. Bids in USDG.
14. At settlement, the winning bid becomes the initial Harberger price.

### 12.2 Governance end-state

After 30 days post-launch :
- Renderer mutability is renounced. The visual is then immutable.
- Treasury multisig signers are publicly disclosed.
- Indexer endpoints are decentralized (community-maintained list).
- The deployer key is destroyed (proof-of-burn published on chain).

The protocol is then *complete and frozen*, no upgradeability, no admin, no kill switch. Only the perpetual Harberger auction continues, forever.

### 12.3 Failure modes acknowledged

If the artifact never attracts a Harberger bidder above the floor, The Wick cycles between foreclosure and floor-price holding. The cANDLE token continues to function as a token. The hook continues to print candles. Nothing is ever bricked. This is the system's graceful-degradation property : the worst case is "no Harberger demand", not "everything stops".

---

## 13. Future extensions

### 13.1 SnapshotMinter (Phase 2)

A separate ERC-721 collection where anyone may pay a fee `s` (initial proposal : 20 USDG) to mint a frozen snapshot of the current buffer state, a *print* of a memorable session (an earnings-day frenzy, a Fed-minute cascade). Fee splits 50 % to the current Wick holder, 50 % to treasury.

This creates :
- A revenue stream for the Wick holder (rationalizing higher posted prices).
- A secondary collectibles market that lives off the activity of the primary artifact.
- A historical record of the market's memorable sessions.

### 13.2 The Market Chart (Phase 3, speculative)

A version of the hook family that listens to the chain's *stock-token* pools (AAPLx, TSLAx, SPYx…) and aggregates prints across them into a second artifact row. The Wick would then literally print the whole onchain stock market, the full realization of the candle thesis. Requires per-pool hook adoption or a keeper-fed aggregator ; deferred until phase 1 dynamics are observed.

### 13.3 Holder bounty (Phase 3, speculative)

A small percentage of swap fees (0.1 %) routed to the current Wick holder, in proportion to time held. Strengthens the holder's economic position. Considered ; risk is that it crowds out LP rewards. Deferred for empirical measurement post-launch.

---

## 14. Glossary and references

### 14.1 Glossary

- **The Wick** : the singular ERC-721 NFT minted at deployment with `tokenId = 0`.
- **cANDLE / CANDLE** : the ERC-20 token, ticker CANDLE, fixed supply 1 B.
- **Candle** : a 16-byte struct in `CandleHook` representing one block's worth of pool activity ; also, in market folklore, one bar on the chart.
- **Print** : a candle rendered on The Wick ; colloquially, any swap that lands in the buffer.
- **Buffer** : the 32-entry circular array `Candle[32] buffer` in `CandleHook`.
- **Head** : the storage `head` index of the most recently written candle.
- **Halt state / THE WICK IS OUT** : the visual decay applied when `block.number - lastBlock > 345 600`.
- **Harberger tax** : continuous tax proportional to a self-assessed posted price, denominated in USDG.
- **Posted price** : the holder's self-assessed valuation, used as tax base and instant-buy price.
- **Foreclosure** : transition to `holder = address(0)` when `taxBalance` is exhausted.
- **Buyback-and-burn** : routine purchase of cANDLE with collected USDG, immediately burning the bought amount.
- **USDG** : the dollar stablecoin native to the Robinhood Chain ecosystem.

### 14.2 References

- Posner, E. and Weyl, G. (2018). *Radical Markets : Uprooting Capitalism and Democracy for a Just Society*. Princeton University Press.
- Adams, H. et al. (2024). *Uniswap v4 Core*, github.com/Uniswap/v4-core
- Adams, H. et al. (2024). *Uniswap v4 Periphery*, github.com/Uniswap/v4-periphery
- Robinhood Chain documentation, docs.robinhood.com/chain
- de la Rouviere, S. (2019). *This Artwork is Always On Sale*, thisartworkisalwaysonsale.com
- wAVE (2026). *A Living Seismograph of Liquidity*, the direct predecessor of this construction.
- Buterin, V. (2018). *On Radical Markets*. vitalik.ca/general/2018/04/20/radical_markets.html
- ERC-721 specification, eips.ethereum.org/EIPS/eip-721
- ERC-20 specification, eips.ethereum.org/EIPS/eip-20

---

**End of document.**
*v1.0, drafted for pre-audit circulation. Subject to revision based on audit findings.*
