# M3 · On-chain and money (T30–T33) 🔒

Every ticket here moves real funds. Human line-by-line review, testnet runs and recorded tx hashes in each PR are mandatory before merge.

Exit gate: on testnet, 23 slices executed over 7 days (or accelerated schedule in test mode), each bought and burned in one transaction, never above 1% of liquidity; treasury split exact to the wei; ledger matches the chain.

---

## T30 · BuybackBurner contract 🔒 ⚠️ Pons

**Goal** The only Vivra contract: buy a token with ETH and burn everything received, in one transaction, under hard caps.

**Depends on** T00

**Read first** `annexe-contrats.md` (entire page), `buyback-bot.md`

**Build** `contracts/src/{IBuybackBurner.sol,BuybackBurner.sol}`, `contracts/test/{BuybackBurner.t.sol,BuybackBurner.fork.t.sol}`, `contracts/script/Deploy.s.sol`, `foundry.toml`

**Steps**
1. Start from the interface and skeleton of annexe D verbatim (immutable owner, caps, operator, pause, events, errors).
2. Implement `_buyOnCurve` and `_buyOnV4Pool` using the Pons curve ABI and the Uniswap v4 router / PoolManager path used by the Meme hook. ⚠️ If the exact call path or the hook's fee behaviour is unclear from the verified ABIs, STOP and ask; do not guess.
3. Refund unused ETH to the operator in the same tx. Assert the contract holds 0 of the bought token at the end.
4. Foundry tests: every row of the annexe D test table + fuzz on `amountIn`/`minOut` + fork tests on a recorded mainnet block for one curve token and one graduated token.
5. Deploy script reading owner, operator, caps from env; prints the address; verification command in README.

**Done when**
- [ ] `forge test` green (unit + fuzz, 1,000 runs)
- [ ] `forge test --fork-url $RPC_URL_MAINNET` green on both routes
- [ ] Deployed on testnet; address + verified explorer link in the PR
- [ ] Gas report included in the PR

**Out of scope** Scheduling (T31).

---

## T31 · Buyback planner and executor 🔒

**Goal** Plan ~23 secret random slices over 7 days and execute them safely.

**Depends on** T02, T11, T22, T30

**Read first** `buyback-bot.md`, `annexe-base-de-donnees.md` (`buyback_plans`, `buyback_slices`), `parcours-4.md`

**Build** `packages/core/src/buybackPlan.ts`, `apps/workers/src/jobs/{buyback.start,buyback.slice,buyback.refill}.ts`

**Steps**
1. `planBuyback({ envelopeWei, capWei, start, end, slices=23, seed })` (pure): random times with min 2h spacing, amounts sum ≤ min(envelope, cap); returns schedule. Times encrypted (`SLICE_SCHEDULE_KEY`) before storage.
2. `buyback.start` at J+1: computes envelope (reserve + leftovers, capped at the token's market cap at vote time), creates plan + slices, schedules delayed BullMQ jobs at each time.
3. `buyback.slice`: re-read liquidity; size = min(planned, 1% of liquidity); quote; `minOut` with 2% slippage; call `buyAndBurn` via `sendTx`; on revert/slippage → `skipped` + alert, never retry bigger; write ledger + publish WS `slice.executed`; publish the tx after execution only.
4. Early stop at J+3 if average volume hasn't doubled vs the 7 days before the vote → remaining slices `skipped`, leftover flagged for next token.
5. Curve token graduating mid-plan → stop per spec (setting).
6. `buyback.refill` daily: top up the hot wallet from reserve up to one day of slices (manual signature if the reserve is a team wallet: create a validation instead).
7. Same planner reused for `$VIVRA` buybacks from CTO fees (target `vivra`).

**Done when**
- [ ] Property tests: amounts never exceed envelope/cap; ≥ 2h spacing; deterministic for a given seed
- [ ] Executor test with mocked chain: slice > 1% liquidity is resized; slippage revert → `skipped` + alert, no retry
- [ ] Early-stop test on fixture volumes
- [ ] Testnet accelerated mode (`BUYBACK_TEST_SPEEDUP=1`, 23 slices in 23 min): all burned, tx hashes in the PR

---

## T32 · Treasury daily job 🔒 ⚠️ Pons

**Goal** Sweep, claim and split $VIVRA fees every day; claim CTO fees into the Fees CTO wallet for the $VIVRA burn.

**Depends on** T02, T10

**Read first** `token-vivra-et-tresorerie.md`, `cto-pons-et-frais.md`, `annexe-contrats.md` (Job quotidien), `questions-ouvertes.md` (Pons questions)

**Build** `apps/workers/src/jobs/treasury.daily.ts`, `packages/core/src/split.ts`

**Steps**
1. Read pending fees (hook or curve); sweep if needed; handle `InternalSwapRequiresOperator` by skipping and alerting.
2. Claim from the escrow for `Collecte` and `Fees CTO` wallets. ⚠️ `claim()` vs `claim(uint256)`: detect from the verified ABI; if both exist or neither matches, stop and ask.
3. `split(amountWei)` (pure): 17/37 team, 15/37 buyback reserve, 5/37 AI; remainder wei goes to buyback reserve; sum must equal input.
4. Transfers + ledger rows (`fees_in`, `split`, `cto_fees_in`); attribution per CTO token from escrow `Credited` events.
5. AI wallet: create a manual task (validation) "swap to USDC and bridge to Base for Surplus" with the amount; automation of the bridge is out of scope for V1.

**Done when**
- [ ] `split` property test: parts always sum to input exactly, ratios within 1 wei
- [ ] Testnet run on a test token with `creatorTaxBps=300`: claimed and split, ledger matches balances to the wei (PR includes tx hashes)
- [ ] Running the job twice the same day does nothing the second time (idempotency test)

---

## T33 · Ledger and Pons CTO tracking

**Goal** Public ledger API and live tracking of each CTO request until fees flow.

**Depends on** T01, T02, T32

**Read first** `cto-pons-et-frais.md`, `annexe-api.md` (`/ledger`, `/wallets`), `parcours-5.md`

**Build** `apps/api/src/routes/{ledger,wallets}.ts`, `apps/workers/src/jobs/tracking.cto.ts`, admin page `apps/admin/app/cto/page.tsx`

**Steps**
1. `GET /ledger` with filters + cursor; `GET /wallets` with live balances.
2. `cto_requests` lifecycle: draft (dossier generated by CM step) → submitted (team clicks after manual submission on cto.ponsfamily.com) → accepted/refused (team) → `recipient_pending` (detected `pendingCreatorFeeRecipient` = Fees CTO wallet) → `recipient_active` (event `CreatorFeeRecipientUpdated`).
3. Daily check for each CTO token; alert on status change.

**Done when**
- [ ] Ledger API test: filters and pagination return stable order
- [ ] Fixture events drive a request from `submitted` to `recipient_active` (test)
- [ ] Admin page shows each request with its status and dates
