// xl.money docs :: machine build :: for agents, not followers
// chain: robinhood-chain (id 4663)  |  stable: contracts, fee model
// derived: keeper gates, delivery timing  |  always verify on-chain
// raw endpoint: https://xl.money/docs/raw
// ───────────────────────────────────────────────────────────────

# XLINK technical reference

This is the canonical technical description of XLINK: what it is, exactly how a dollar
moves from a trade on a bonding curve to a notification in someone's X Money account, what
is enforced on chain versus what depends on a human, and how to check every claim below
yourself. It is written for a person auditing the product and for an AI agent reading
xl.money and trying to describe it accurately. Every fact below names the file it came
from. Where a value could change on chain (a fee, a threshold, an address), the file and
the exact getter to re-read it live are both given, because a document goes stale and a
chain read does not.

Status as of this writing (2026-09-13): the v2.1 contracts are deployed on Robinhood Chain
(chain id 4663) and bytecode-verified against the compiled artifacts, the identity and ledger
services, the signer and the keeper run against them, and every automated leg is switched on:
one-shot claims are paid by the keeper, community delivery and the fiat rail execute
automatically, and holder reflections are distributed each epoch with the multiplier. The
launch, fee-split and claim legs have been exercised with real value on the live contracts: a
coin launched through the public site for a third-party handle, real trades split fees into the
pot, the holders' pool and the treasury exactly as the contracts compute, and the handle's
owner claimed the pot with a real X sign in. Community delivery to X Money and the fiat rail are
switched on but have not yet been exercised on v2.1 (the rail itself was proven standalone; no
v2.1 on-chain delivery has run). Everything under "Known limitations and open items"
below is real and current, not boilerplate.

## Links and addresses

The handful of values a reader reaches for first, gathered in one place. Each row's source
column names the file or config constant that is the actual source of truth; if this table
and that source ever disagree, the source wins, not this table.

| What | Value | Source |
|---|---|---|
| X account | [`@xLinkMoney`](https://x.com/xLinkMoney) | `NEXT_PUBLIC_BRAND_HANDLE` (`app/src/lib/env.ts`'s `brandHandle`), surfaced to the docs page via `app/src/lib/site-links.ts`'s `socialLinks`. This page is statically generated, so this row reflects whatever value was configured at the last production build, not necessarily this instant; the account can be renamed with a single env var edit, followed by a rebuild and deploy, no other edit required. |
| `$XL` token | [`0x1cDb289BeFDFaC8aF945a288BCdcCc382cB34d32`](https://hoodscan.co/address/0x1cDb289BeFDFaC8aF945a288BCdcCc382cB34d32) | $XL is live, launched for XLINK's own handle `xlinkmoney` (X user id `2098113645448249347`) on the `HandleVaultFactoryV21` above. Pot: [`0x61Bf66304c065FAa052112d6f9e52f751b9ebD91`](https://hoodscan.co/address/0x61Bf66304c065FAa052112d6f9e52f751b9ebD91). Bonding curve, graduated: [`0xc3588DA017090047d1a4E8bB0669b56C829F7140`](https://hoodscan.co/address/0xc3588DA017090047d1a4E8bB0669b56C829F7140). Confirmed live on chain 4663: deployed bytecode present at all three addresses, and the token's `name` reads "X Link", `symbol` reads "XL" and `decimals` reads 18. `app/src/lib/site-links.ts`'s `xlTokenAddress` reads `NEXT_PUBLIC_XL_TOKEN_ADDRESS`; setting that env var to this address and rebuilding is what makes the site's own contract chip pick it up too. The old `xcoinpad` house test coin is a separate, unrelated address, described in "The retired v1 factory, and why it is retired" below; it is not $XL. |
| `HandleVaultFactoryV21` (v2.1, live) | [`0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36`](https://hoodscan.co/address/0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36) | "Contracts and addresses on chain 4663" below; `contracts/DEPLOYMENTS.md`; the deploy broadcast |
| `HandleVaultV21` implementation | [`0x810d0a4A0B1d0c787819896C7f9aaB06C36cEd3d`](https://hoodscan.co/address/0x810d0a4A0B1d0c787819896C7f9aaB06C36cEd3d) | same as above |
| `ReflectionDistributor` (holder reflections pool) | [`0xD5587eaB8C3e44bD8772139B00123f0b65632016`](https://hoodscan.co/address/0xD5587eaB8C3e44bD8772139B00123f0b65632016) | same as above; read `reflectionDistributor` on the factory |
| `HandleVaultFactory` (v2, previous; still consulted by v2.1 for squat prevention) | [`0xcB1C296F4b964cC03Ba89D4414Cf7B9BA1da117b`](https://hoodscan.co/address/0xcB1C296F4b964cC03Ba89D4414Cf7B9BA1da117b) | "The v2 factory (previous)" below; read `v2Factory` on the v2.1 factory |

Explorer: [hoodscan.co](https://hoodscan.co) (`NEXT_PUBLIC_EXPLORER_BASE`, `app/src/lib/env.ts`'s
`explorerBase`). Every address above is also cited in full, with deploy transactions and block
numbers, in "Contracts and addresses on chain 4663" below.

## What XLINK is

XLINK lets anyone launch a Pons V2 bonding-curve coin "for" an X handle. The coin's on
chain creator fee recipient is not a person's wallet and not XLINK's wallet: it is a
per-handle smart contract, `HandleVaultV21` (a "pot"), plus, for a coin with holder
reflections on, a per-coin `FeeSplitter` in front of it. Money leaves a pot in exactly three
ways, all on chain: the handle's verified owner claims it in one shot (sign in with X, name a
wallet, the whole available balance is paid there at no fee); anyone asks XLINK to deliver an
unclaimed pot to that person's X Money account for a fee, in public; or, for a pot nobody has
claimed and nobody has traded against for 14 days, XLINK's owner key may mark it abandoned and,
after a further 14-day public notice window, sweep it to the platform treasury and nowhere
else. No admin key has a function that pays a pot's balance to an address of the admin's
choosing: a claim's destination is fixed by the oracle-signed attestation, a delivery's
destination is the delivery wallet snapshotted at request time, and the sweep can only pay
`platformTreasury` (`contracts/src/v21/HandleVaultV21.sol:543,634,706`;
`contracts/src/v21/AbandonmentManagerV21.sol:673`). Those properties are proven by fork tests
that exist specifically to fail if they stop being true:
`test_claim_fullBalancePayout_pendingPlatformShareReserved`,
`test_ec14_guardianRevokeOracle_invalidatesAttestation` and
`test_sweepAbandonedVault_onlyFactoryCanCallVaultSweep` (`contracts/test/v21/ClaimV21.t.sol`,
`EmergencyControlsV21.t.sol`, `AbandonmentV21.t.sol`).

The differentiator against a plain fee-split launchpad is the payout destination: fees are
meant to land as an X Money peer to peer payment from XLINK's own X account, with a public
note, so the handle owner gets a real X notification and can share it
(internal decision record, not published: "the whole
point of XLINK is that fees earned by a coin launched for an X handle end up in that
person's X Money balance"). An on-chain-only release to a wallet is the honest fallback for
someone who would rather self-custody than wait for or trust the X Money leg; it is not the
product's headline path.

XLINK is the rebuild of an earlier, dishonest project by the same operator,
`xcoins.fund`, whose "fees bridged straight into X Money" claim never happened for any coin
except its own, and whose per-coin fee recipients were plain server-held wallets, not
contracts . XLINK's whole design is a reaction
to that: the per-handle vault is non-custodial in the sense that matters (no server-held
key can move funds out of it against its owner's will; see "The trust model" below), and
no present-tense claim that outruns what is actually live on chain and on the rail, checked
below (
discipline was held while the legs were being built). That claim is narrower
than "XLINK never touches a handle's money": once a vault's balance leaves it through
`executeDelivery`, it lands first in `deliveryWallet`, an XLINK-controlled address,
before continuing on to PayPal and then X Money (see "The delivery fee" and "The X Money
receive flow, as verified" below); and a pot with no claim, no fee activity and no reflection claims for 14 days may be marked
abandoned by the factory owner and, after a further 14-day public notice window, swept to
the platform treasury (see "Abandoned pots" under "Known limitations and open items" below).
Both are real, named custody hops on a stated schedule, not a hidden one: the guarantee
is that nobody can redirect a vault's funds against its owner, not that the money never
touches an address XLINK controls.

## The end to end flow

Every hop, named, in order. Contract function names are exact; file paths are given for
each hop so a reader can go straight to the source.

1. **A vault is created for an X handle.** `HandleVaultFactoryV21.createVault` deploys a
   deterministic EIP-1167 minimal proxy clone of the shared `HandleVaultV21` implementation,
   keyed by the handle's numeric X user id, never by the handle string (a handle string can
   be released and reused; the numeric id cannot). Before creating, the factory consults the
   previous v2 factory's `vaultOfHandle` and refuses (`HandleTakenOnV2`) if that handle already
   has a v2 vault, so no handle can be squatted across the two factories. There are two ways
   to call it: XLINK's own allowlisted keeper key can call the two-argument overload directly,
   and anyone else must present an oracle-signed `LaunchTicket` to the four-argument overload
   (`contracts/src/v21/HandleVaultFactoryV21.sol:593,598,619`).
2. **The coin launches through the vault.** `HandleVaultV21.launch` calls Pons V2's
   `PonsV2LaunchFactory.launchToken`, forwarding exactly Pons's own live `launchFee` and
   nothing more, with one extra argument v2 did not have: `reflectionsEnabled`, on by default
   in the launch form and pinned forever at the vault's first launch. With reflections off the
   vault itself is the coin's `creatorFeeRecipient`; with reflections on the factory deploys a
   fresh per-coin `FeeSplitter` clone and sets that as the recipient, so the holders' share can
   be carved out before anything reaches the vault. Same two-path shape as vault creation: an
   allowlisted launcher calls the plain overload, everyone else needs an oracle-signed
   `LaunchTicket` naming their own address as the launcher for that exact vault
   (`contracts/src/v21/HandleVaultV21.sol:287,297`; `HandleVaultFactoryV21.sol:982`;
   `app/src/lib/launch-tickets.ts:124`). Every coin launched under the current factory must
   pair against USDG; `launch` reverts `PairNotAllowed` for a native ETH pair.
3. **Trading accrues a creator tax and Pons's own base fee inside Pons's own escrow**,
   not inside the vault yet. This is Pons V2's mechanism, external to XLINK's contracts;
   XLINK reads it via `PonsV2FeeEscrow.balanceOf` / `balanceOfToken`. For a reflections-on
   coin the keeper first calls `FeeSplitter.collect(curve)`, which sweeps the curve, pays the
   community share straight into the `ReflectionDistributor` pool for that coin, and re-credits
   the remainder into Pons's escrow under the vault's address, so the vault's own `claimFees`
   cannot tell it apart from a direct Pons payment (`contracts/src/v21/FeeSplitter.sol:257`,
   .
4. `claimFees` **pulls the accrued amount out of Pons's escrow into the vault** and, in
   the same transaction, computes and pays the platform's fixed share of that delta to
   `platformTreasury` before leaving the remainder as the handle's available balance. There is
   no keeper tip in v2.1; the keeper pays its own gas
   (`contracts/src/v21/HandleVaultV21.sol:447`). See "The fee model" below for the exact split.
5. **The handle's owner claims by X sign in.**  runs the X OAuth 2.0 PKCE
   flow, resolves the caller's numeric `xUserId`, takes the wallet the owner wants paid, and
   issues an EIP-712 `Attestation` `{handleHash, xUserId, to, deadline, nonce, oracleEpoch}`
   signed by the identity oracle key inside the signer Worker. The `to` field is bound to the
   signed-in X proof, so a leaked attestation cannot be redirected, and the deadline may not
   be more than one hour out (`MAX_ATTESTATION_TTL`, `contracts/src/v21/HandleVaultV21.sol:130`;
   .
6. **`claim` pays the whole pot in one shot, at no fee.** Anyone may submit the attested
   claim (XLINK's keeper does, from a gas-only key, so the owner pays no gas); the vault
   checks the handle, user id, nonce, oracle epoch and signature, then pays 100% of the
   available pair-token balance to `Attestation.to` and increments the per-vault
   `claimNonce`. There is no persistent owner, no contest window, no re-bind and no partial
   release: the next claim is a fresh sign in and a fresh attestation
   (`contracts/src/v21/HandleVaultV21.sol:543`;,
   `CLAIMS_PAYOUT_ENABLED`).
7. **Or, instead of a claim, anyone can ask XLINK to deliver a pot's balance to X Money:
   permissionless `requestDelivery` then `executeDelivery`.** This is the "community
   delivery" path, and since v2.1 it is also how a handle's owner gets X Money: there is no
   fee-free owner route to X Money any more, because there is no owner-only `release`. The
   request has no minimum balance and no pre-empt window today: `deliveryDelay` is deployed
   at `0` (the contract's `MIN_DELIVERY_DELAY`), so a request is executable immediately; the
   factory owner can raise it up to 7 days at any time with no timelock, so read
   `deliveryDelay` live rather than trusting this number
   (`contracts/src/v21/HandleVaultV21.sol:593`; `HandleVaultFactoryV21.sol:176,177,825`).
8. **`executeDelivery` pays a delivery fee to `platformTreasury` and the rest to
   `deliveryWallet`.** Only `factory.deliveryOperator` may call it; that role is XLINK's
   gas-only keeper key, distinct from the delivery wallet, the deployer and the oracle. The
   fee and destination used are the ones snapshotted when the request was made, never a live
   factory read at execution time, so a later fee or wallet change can never re-price a
   request already in flight (`contracts/src/v21/HandleVaultV21.sol:634`; read
   `deliveryOperator` live).
9. **USDG in the delivery wallet is bridged one hop to PYUSD at PayPal's own receive
   address on Ethereum**, entirely off chain 4663, via a single LI.FI transaction
   (; verified live 2026-09-11, 10 USDG in one chain-4663
   transaction landed as 9.8692 PYUSD at PayPal's deposit address about 4 seconds later,
   .
10. **PayPal credits the PYUSD, and a human sells it for US dollars** inside PayPal. This
    is a manual tap: PayPal has no API to auto-convert received crypto and no auto-sell
    setting for it .
11. **PayPal's own daily automatic transfer, or a manual PayPal instant transfer (1.5%,
    minutes), moves the US dollar balance into X Money**, which is a linked bank inside
    PayPal's own UI, exactly like linking any other bank
    (; PayPal to X Money instant
    transfer measured live at 1.5% with a $0.50 minimum).
12. **A human sends the X Money peer to peer payment to the handle owner**, from XLINK's
    own X account, with a note. This is the one remaining manual step in the money's actual
    path and is intentionally never scripted; see "What is not automated" below.
13. **A public proof is posted.** The keeper only posts the "delivered" announcement after
    it independently observes, via the the delivery record, that the operator actually marked the
    payment sent; it never announces a payment before it went out
    (
    before").
14. **The public activity feed shows the whole lifecycle.** `GET /activity` merges on
    chain `Launched` / `FeesClaimed` / `HandleClaimed` / `DeliveryRequested` / `Delivered`
    events (and the previous factories' `Bound` / `Released` / `AutoReleased`, under the same
    kinds) with the public-safe fields of the same the delivery record rows, so a pending request, a
    sent payment, and a claimed or paid-out state are all visible without trusting a
    dashboard ().

The whole chain, compressed to one line, matching the operator's own description
:
Pons trade to Pons escrow (via the coin's FeeSplitter when reflections are on) to
`claimFees` into the vault to owner sign in and one-shot `claim` to a wallet, or community
`requestDelivery`/`executeDelivery` to USDG bridged to PYUSD at PayPal to a manual sell to
US dollars to a transfer into X Money to a manual peer to peer send with a public note.

## The fee model, exactly as configured

Every number here is read from the actual deployed `HandleVaultFactoryV21` constructor
arguments (the deploy broadcast, summarized in
`contracts/DEPLOYMENTS.md` and `contracts/deployments/v21-2026-09-13.json`) and cross-checked
against .1: community reflections" sections and
`contracts/src/v21/HandleVaultV21.sol`, `HandleVaultFactoryV21.sol` and `ReflectionFeeMath.sol`
directly. Nothing here is a plan; this is what is live on chain today.

**Two fees exist, and they apply at two different moments.** The creator tax and Pons's own
base fee are set once, at a coin's first launch, and apply every time `claimFees` pulls
money out of Pons's escrow into the vault. The delivery fee applies once, only if and when
the community delivers an unclaimed vault's balance to X Money through the permissionless
`requestDelivery`/`executeDelivery` path, on top of whatever `claimFees` already took.
The owner's one-shot `claim` to their own wallet pays neither fee beyond what already
landed in the vault; it always moves 100% of the vault's available balance, with no fee
(`contracts/src/v21/HandleVaultV21.sol:543`, no fee logic in that function's body). A third
slice, the holders' reflections share, is carved out before `claimFees` for coins launched
with reflections on; see "Reflections" below.

### The creator tax floor and its 80/20 split

- `HandleVaultFactory.floorTaxBps` is deployed at **100 (1.00%)**. This is both the lowest
  `creatorTaxBps` a coin may launch at, and the base XLINK's own claim-time share is computed
  against (.
- `HandleVaultFactory.platformShareOfFloorBps` is deployed at **2,000 (20% of that 1% floor)**,
  capped on chain at `MAX_PLATFORM_SHARE_OF_FLOOR_BPS = 2_000`
  (`contracts/src/v21/HandleVaultFactoryV21.sol:173`) after round 5 of the external audit lowered it
  from an original 5,000 (the audit record. So of the 1%
  floor tax itself: **0.8% of volume to the handle, 0.2% of volume to XLINK**
  (`app/design/PILL-FACTS.md` line 8: "tax floor 1%: 0.8% handle + 0.2% XLINK").
- Separately, Pons's own base curve fee for the current launch config is 1% of volume,
  which Pons's own fixed policy (read live at launch time, not configured by XLINK) splits
  0.7% of volume to the coin's creator fee recipient (the vault) and 0.3% of volume kept by
  Pons's protocol (;
  `app/src/lib/launch.ts:34`, `PONS_BASE_SHARE_BPS = 30`).
- **Added together, the minimum total tax on every trade at the floor is 2.00% of
  volume**: 1% XLINK floor plus 1% Pons base fee. Of that 2%, the handle keeps 1.5%
  (0.8% plus 0.7%), XLINK keeps 0.2%, and Pons's own protocol keeps 0.3%. This is the "2%
  creator tax floor" figure used in operator notes and product copy
  ; the 80/20 split specifically names
  XLINK's own 1% component of that 2%, never the whole 2%.
- **Above the floor**, a launcher may set `creatorTaxBps` up to Pons's own
  `maxCreatorTaxBps`, which was read live as **1,000 (10%)**
  (.ts:32`,
  `MAX_CREATOR_TAX_BPS = 1000`). Every basis point above the 1% floor goes **100% to the
  handle**; XLINK's own cut of volume is pinned at 0.2% regardless of how high the launcher
  sets the tax (
  DENOMINATOR"). Two different, correctly distinct ways to express the handle's resulting
  share exist in this codebase and should not be confused:
- **Share of the money** `claimFees` **actually delivers to the vault** (excludes Pons's own
  protocol cut, which never reaches the vault at all): at the 1% floor this is
  20 / 170 is about 11.76% to XLINK and 150 / 170 is about 88.24% to the handle; at the
  10% cap it is 20 / 1070 is about 1.87% to XLINK and 1050 / 1070 is about 98.13% to the
  handle. This is `HandleVault.platformShareOf`'s exact, on-chain, currently-pinned-per-vault
  formula (. Those two ratios are for a reflections-off
  coin. With reflections on, the vault's pinned denominator is reduced by the community share
  (`platformShareDenominatorBps = T + 70 − C`, `contracts/src/v21/ReflectionFeeMath.sol:66-97`),
  because the holders' `C` never reaches the vault at all: at the 1% floor with reflections on,
  what reaches the vault is 120 bps of volume, of which 20 / 120 is about 16.67% to XLINK and
  100 / 120 is about 83.33% to the handle; XLINK's 0.2% of volume is unchanged either way.
- **Share of the total volume-based tax the trade pays, including Pons's own protocol
  cut** (a marketing simplification, computed by `app/src/lib/launch.ts`'s
  `creatorTaxSplit`, used on `/launch` and `/h/[handle]`): at the 10% cap,
  vaultBps is 1000 minus 20 plus 70 equals 1050, against a total of 1050 plus 20 plus 30
  equals 1100, a ceiling of **95%** at the current 10% tax cap (`app/src/lib/launch.ts:53`).
  A home-page "Up to 95%" marketing pill built on this figure was removed in the 2026-09-12
  UI round 6 pass in favor of a first-mover headline claim instead
  (`app/src/components/xl/orbit-center.tsx`'s own comment: "Never revert this to 'Up to 95%'
  without a fresh operator call"). Today the figure only appears, computed live via
  `creatorTaxSplit`, in the three-line fee breakdown on `/launch`
  (`app/src/app/launch/LaunchForm.tsx:1058` to 1059) when a launcher actually sets
  `creatorTaxBps` to the cap; it answers "of everything this trade pays in tax, how much
  reaches the handle," not "of what the vault claims, how much is XLINK's." Note that
  `creatorTaxSplit` does not subtract the holders' reflections share, so on a reflections-on
  coin (the default) the "to the pot" figure it prints is the pot plus the holders' pool
  together, not the pot alone.
- **The fee split is pinned per vault at first launch and can never be re-priced by a
  later factory-level change.** `TaxPinned` / `pinnedCreatorTaxBps` on the vault; a relaunch
  at a different tax reverts instead of silently changing the split on already-accrued fees
  (the audit record.
- Both `floorTaxBps` and `platformShareOfFloorBps` are owner-settable but only affect
  vaults that have not launched yet, and both sit behind a 7-day timelock as
  defense-in-depth (`contracts/src/v21/HandleVaultFactoryV21.sol:758,778`;
  `FLOOR_TAX_BPS_TIMELOCK` and `PLATFORM_SHARE_OF_FLOOR_BPS_TIMELOCK` at lines 178 to 179,
  both 7 days; a floor below 100 bps is refused outright at proposal time,
  `FloorTaxBpsBelowMinimum`, line 139).

### Reflections: the holders' share, live

- **Reflections are a per-launch toggle, on by default, pinned forever at a vault's first
  launch** (`pinnedReflectionsEnabled`, `ReflectionsTogglePinned`,
  `contracts/src/v21/HandleVaultV21.sol:154`; default `true` in
  `app/src/lib/launch-tickets.ts:124`; the toggle is in step 2 of `/launch`).
- **The split, in bps of volume, from `ReflectionFeeMath.computeSplit`
  (`contracts/src/v21/ReflectionFeeMath.sol:66-97`):** community `C = 50 + (T − 100) / 2`
  when on, `0` when off, where `T` is the creator tax; XLINK stays `floorTaxBps ×
  platformShareOfFloorBps / 10000 = 20`; the handle gets the rest. At the 1% creator-tax floor (T = 100; 2% total trade tax)
  with reflections on: **0.5% of volume to holders, 1.0% to the handle, 0.2% to XLINK, 0.3%
  to Pons**; with reflections off the holders' 0.5% folds back into the handle's 1.5%. Every
  extra 1% of tax above the floor splits half to holders and half to the handle when on, and
  all to the handle when off (`contracts/REFLECTIONS-DESIGN-MEMO.md` section 5). A
  reflections-on coin must set `T` on the 50-bps grid (`CreatorTaxNotOnGrid`).
- **Mechanism.** The factory deploys one `FeeSplitter` clone per reflections-on coin
  (`HandleVaultFactoryV21.deploySplitter`, implementation
  `0x6b47541a9771e518366dc06a3A12332AF02Bb683`) and sets it as the coin's Pons
  `creatorFeeRecipient`. Permissionless `collect(curve)` sweeps the curve, deposits `C` into the
  shared `ReflectionDistributor` (`0xD5587eaB8C3e44bD8772139B00123f0b65632016`, pool keyed by
  the splitter's address) and re-credits the remainder into Pons's escrow under the vault, so
  the vault's unmodified `claimFees` then applies its own pinned XLINK numerator to what
  arrives (`contracts/src/v21/FeeSplitter.sol:14-59,257`; `ReflectionDistributor.sol:165`).
- **Distribution is push-primary, pull-fallback, with a multiplier of up to 2x.** Each epoch
  the keeper snapshots holders from `Transfer` logs (curve, pool, locker, vault, splitter and
  dead addresses excluded), weights each holder's time-weighted balance by a multiplier
  `min(S × U × B × L × D, cap)` built from hold streaks, sell penalties, burns and locks, commits
  a cumulative Merkle root (`commitEpoch`) and pays qualifying EOA holders directly
  (`pushBatch`), XLINK paying the gas; anyone a push skips (a contract holder, a rejecting
  recipient, a sub-dust entitlement) stays pull-claimable against the same root via `claim`
  for as long as the pool exists. Cumulative totals make push and claim replay-idempotent
  (`contracts/src/v21/ReflectionDistributor.sol:14-49,193,227,310`;
   section 4;, `EPOCH_ENABLED`,
  `EPOCH_PUBLISH_ENABLED`, both on in production since 2026-09-13).
- **Trust statement, verbatim from the contract:** the epoch keeper (`factory.epochKeeper`,
  read it live) is trusted with a pool's funds up to what it has allocated; the contract
  enforces pool isolation and solvency, not allocation honesty; the published root makes a
  dishonest allocation publicly provable but not preventable. The guardian can `pause` the
  distributor and any splitter instantly (`ReflectionDistributor.sol:384`).
- **Proven live on 2026-09-13:** on the first reflections-on coin launched through the public
  site (creator tax 2%, so `C = 100`), one collect-and-claim split 4.658 USDG into 2.588 to the
  pot, 1.725 to the holders' pool and 0.345 to the treasury, which is exactly 150 : 100 : 20 of
  270 bps; the pot was then claimed in full by the handle's owner with a real X sign in.

### The delivery fee

- `HandleVaultFactoryV21.deliveryFeeBps` is deployed at **500 (5%)**
  (`contracts/script/DeployV21.s.sol:265`; `contracts/DEPLOYMENTS.md` "Factory on-chain
  state"), capped on chain at `MAX_DELIVERY_FEE_BPS = 1_000` (10%)
  (`contracts/src/v21/HandleVaultFactoryV21.sol:175`), settable instantly by the owner with
  no timelock (`setDeliveryFeeBps`, `contracts/src/v21/HandleVaultFactoryV21.sol:819`).
- **5% is the number the operator settled on 2026-09-12 on the previous v2 factory** (raised
  there from a 200 (2%) deploy value, tx `0xbfaaae0d…02bc`, .1
  was deployed at 500 directly**, to cover the measured cost of the fiat leg (about 1.5% for
  a PayPal instant transfer, about 1.3% for the bridge and swap hop at small size, plus gas
  and margin). It remains an owner-settable value with no timelock, so **read
  `deliveryFeeBps` live before trusting this number** (see "How to verify" below) rather
  than assuming it can never move again.
- The fee is paid to `platformTreasury`; the remainder goes to `deliveryWallet`
  (`contracts/src/v21/HandleVaultV21.sol:634` to 665, .
- **Delivery is paid from the handle's own accrued pot, never from XLINK's own revenue.**
  This is a reversal of an earlier decision: on 2026-09-11 the operator wanted XLINK to fund
  the X Money notification from its own fee share so the influencer's pool stayed untouched
  ; on
  2026-09-12, after the live pipeline test, the operator reversed this explicitly: "We will
  pay the creators from the pot. We will not pay them from our own revenue"
  . The earlier
  own-fees model is superseded on this point; treat the pot-funded model as current.
- There is no owner opt-in and no fee-free owner route to X Money in v2.1: `optInDelivery`,
  `release` and the bound-owner delivery branch were all deleted (`contracts/src/v21/HandleVaultV21.sol:18-58`).
  A verified owner who wants their wallet paid uses the one-shot `claim`, which pays 100% of
  the pot at no fee; a verified owner who wants X Money uses the same delivery path as
  everyone else, and pays the same 5% from the pot. `requestDelivery` is permissionless, has
  no minimum balance, and today no waiting window (`deliveryDelay` is `0`; read it live); the
  guardian can `cancelDelivery` at any time as an incident brake
  (`contracts/src/v21/HandleVaultV21.sol:593,621`).
- **There is no delivery threshold and no auto-release in v2.1.** v2 gated
  `requestDelivery` and `autoRelease` behind a per-vault threshold that the operator had
  already lowered to 1 unit on 2026-09-12; v2.1 removed `autoRelease` and the check itself
  (. The
  factory still exposes a `defaultAutoReleaseThreshold` getter (it reads `69,000,000` on the
  live factory) because the field is kept for storage-layout parity with
  `AbandonmentManagerV21`; no v2.1 vault reads it (`HandleVaultV21.initialize`,
  `contracts/src/v21/HandleVaultV21.sol:235`, takes no threshold). Money stays in the pot,
  whatever its size, until it is claimed, delivered, or swept as abandoned.

## Contracts and addresses on chain 4663

Chain 4663 is Robinhood Chain, an Arbitrum L2, mainnet since 2026-07-01
(`app/design/PILL-FACTS.md` line 7). Free RPC used throughout this project:
`https://rpc.ordofi.network`.

### The current, live factory (v2.1)

| Contract | Address | Deploy tx | Block |
|---|---|---|---|
| `HandleVaultFactoryV21` | `0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36` | `0xa1b08597efe6fe4210dadd0459677c8844fe747d5846e4edbaa58cdf883d9274` | 61,581,481 |
| `HandleVaultV21` implementation | `0x810d0a4A0B1d0c787819896C7f9aaB06C36cEd3d` | `0xce948162c2dc6bbbb377a65994599e2bf0689d3e6409492c70c54b23eb80020b` | 61,579,750 |
| `ReflectionDistributor` | `0xD5587eaB8C3e44bD8772139B00123f0b65632016` | `0x62cca55cc69d469e5107639cf4c3fe373c5c0abebdab36b0a8a17969da2c356c` | 61,579,753 |
| `FeeSplitter` implementation | `0x6b47541a9771e518366dc06a3A12332AF02Bb683` | `0x9e037430bd4345ab1b9ba941d5ff3ec45171376135db8df7adb871dba4e84a1d` | 61,579,751 |
| `AbandonmentManagerV21` | `0xF414fE90210Ff176BBFC38C47e5Fc8d30B2690e0` | `0x6e77f6ed23e31580f6d153cb9c0bcf3b517ed46f466d8b3a8864e70d1535be6c` | 61,579,748 |
| `ReflectionFeeMath` | `0x353CEEF65a054E0dd2ceA0cB137FD57E0AA6Bc05` | `0x9db8f7314392b27bae8bb1dd9d1f52c19c26583c9b7cfa01d96eff7df5100472` | 61,579,746 |

Source: the deploy broadcast (raw transaction receipts),
summarized with deployer nonces and bytecode checks in `contracts/DEPLOYMENTS.md` and
`contracts/deployments/v21-2026-09-13.json`. Five contracts from an aborted first broadcast
(deployer nonces 26 to 30) are orphaned and listed there; do not use them. Deployed 2026-09-13
as a fresh, parallel deployment: no v2 vault was migrated or upgraded, and the v2 factory keeps
operating for the vaults it already has (`contracts/src/v21/HandleVaultFactoryV21.sol:18-25`).

Deployer, owner, guardian and treasury of the live factory are currently the same externally
owned account, `0xf8B6322a0d6dfC2ecD7B89c0E7C5B4dA6376bD44` (`owner`, `guardian` and
`platformTreasury` all read it; `pendingOwner` and `pendingPlatformTreasury` read zero).
This is a known launch-day simplification, recorded as the top open item in
`reports/security/POSTURE-2026-09-13.md`; rotation to fresh keys is scheduled after launch
and will show up first in `pendingPlatformTreasury` / `pendingPlatformTreasuryEta` (7-day
timelock) and `pendingOwner`. The identity oracle is a separate key,
`0xF51EA9f6a6ca1e0d65F8Feb3E1E4517E4607649E`, held only inside a Cloudflare Worker (see "The
trust model" below). The delivery wallet is a distinct address,
`0x62389156bB6E502690846F55f18fbC60916BD828`, required distinct from the owner, guardian,
treasury and oracle by the deploy script itself (`contracts/script/DeployV21.s.sol:275`,
`_requireDistinctDeliveryWallet`). The delivery operator and the epoch keeper are one further
distinct, gas-only key, `0xE585d13afDA7383A59fCF6406c6dEDFa257f7591`, which can execute a
delivery and publish an epoch but cannot choose where a single wei goes. Read `owner`,
`pendingOwner`, `guardian`, `platformTreasury`, `pendingPlatformTreasury`,
`deliveryOperator` and `epochKeeper` live before trusting any of these addresses (see "How
to verify" below).

Bytecode verification: each of the six contracts' on-chain code was diffed against the
compiled artifact's `deployedBytecode` after zeroing the immutable slots, and matched
(`contracts/DEPLOYMENTS.md`, "Bytecode verification method"; instrument `cast code` plus a
diff script; falsification condition: any byte outside the immutable slots differs). Sourcify
source verification for the v2.1 addresses has not been submitted as of this writing, so the
Sourcify endpoint returns no match for them yet; the previous v2 factory and implementation
remain Sourcify exact-match. Check the code yourself:

```bash
cast code 0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36 --rpc-url https://rpc.ordofi.network
cast code 0x810d0a4A0B1d0c787819896C7f9aaB06C36cEd3d --rpc-url https://rpc.ordofi.network
```

### The deployed `FactoryConfig` (v2.1), field by field

Read from the factory's live getters and the deploy script's `_buildConfig`
(`contracts/script/DeployV21.s.sol:243` to 270), matched against the field order in
`contracts/src/v21/HandleVaultFactoryV21.sol`'s `FactoryConfig` struct (line 444):

| Field | Live value | Meaning |
|---|---|---|
| `guardian` | `0xf8B6…bD44` | instant oracle revoke, delivery cancel, distributor/splitter pause; read `guardian` live |
| `oracle` | `0xF51E…649E` | identity attestation and launch ticket signer |
| `platformTreasury` | `0xf8B6…bD44` | receives the claim-time platform share, the delivery fee and any abandoned-pot sweep |
| `requiredPairToken` | `0x5fc5…1d168` (USDG) | every launch must pair against this |
| `floorTaxBps` | `100` (1%) | creator tax floor and platform-share base |
| `platformShareOfFloorBps` | `2000` (20%) | XLINK's share of the floor |
| `deliveryWallet` | `0x6238…D828` | where delivered funds land, after the fee |
| `deliveryFeeBps` | `500` (5%) | delivery fee to the treasury; owner-settable, no timelock |
| `deliveryDelay` | `0` seconds | waiting window before a request can execute; `MIN_DELIVERY_DELAY` is `0`, `MAX_DELIVERY_DELAY` 7 days; owner-settable, no timelock, read live |
| `deliveryOperator` | `0xE585…7591` | only address allowed to call `executeDelivery`; set post-deploy by the owner, read live |
| `epochKeeper` | `0xE585…7591` | only address allowed to commit and push reflection epochs; set post-deploy by the owner, read live |
| `firstBindWindow`, `keeperTipBps`, `keeperTipCapWei`, `defaultAutoReleaseThreshold` | `3600` / `0` / `0.01 ETH` / `69,000,000` | vestigial: kept so the factory's storage layout matches `AbandonmentManagerV21`'s mirror; no v2.1 vault reads any of them (there is no bind window, no keeper tip and no auto-release in v2.1) |

Not in the config struct but fixed at deploy as immutables: `v2Factory`
`0xcB1C296F4b964cC03Ba89D4414Cf7B9BA1da117b` (squat-prevention read on every `createVault`),
`abandonmentManager` `0xF414fE90210Ff176BBFC38C47e5Fc8d30B2690e0`,
`feeSplitterImplementation` `0x6b47541a9771e518366dc06a3A12332AF02Bb683`; and, behind a 7-day
timelock, `reflectionDistributor` `0xD5587eaB8C3e44bD8772139B00123f0b65632016`
(`contracts/src/v21/HandleVaultFactoryV21.sol:151,157,162,193,299`). The handle cooldown
that v2 had is gone entirely, not floored: `handleCooldown` does not exist on the v2.1
factory (a call to it reverts), so a handle may launch any number of coins at any time
(`HandleVaultFactoryV21.sol:39-41`).

### The v2 factory (previous)

| Contract | Address | Notes |
|---|---|---|
| `HandleVaultFactory` (v2) | `0xcB1C296F4b964cC03Ba89D4414Cf7B9BA1da117b` | deploy tx `0x17f008a82a5d46a10d061003c887945ab9a0fa312dbe1e0ae9c7de69ee6451d1`, block 59,831,338 |
| `HandleVault` implementation (v2) | `0x83bE7A2d8101E3aC87bAA0B5D5b9a0Ca0C67e54D` | deploy tx `0xeb2d9a73831b5509ccb977aa5d6df388fa1afe6eee4a714e07ecc30d5e61703e`, block 59,831,315 |

Source: the deploy broadcast. Deployed 2026-09-11 and
superseded by v2.1 on 2026-09-13; both contracts are Sourcify exact-match. The v2 factory
still matters in two ways: the v2.1 factory reads its `vaultOfHandle` on every vault creation
so no handle with a v2 vault can be recreated on v2.1 (`HandleTakenOnV2`), and the v2 vaults
that exist keep their v2 mechanics (bind, release, auto-release, a 12-hour delivery delay)
forever, since a vault's factory is fixed at creation. Its own rotation state is separate
from the live factory's: its guardian was rotated to `0x22c73c5a2632E497e1EAFC06beFc2ae3770e38b8`
and a new treasury `0x0758311D1Ccd468b280496cA07Af43B19a77BFee` is proposed there under its
7-day timelock (`pendingPlatformTreasuryEta` on that factory reads `1789773436`,
`2026-09-18T23:17:16Z`). New handle issuance on v2 is frozen operationally: the signer only
signs tickets for the v2.1 factory (`contracts/ROUND13-CUTOVER.md` "Freeze v2 issuance").
### USDG

`0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168`, 6 decimals, confirmed live on chain 4663
(; `app/design/ACTIVITY-DATA-SOURCES.md` section
2). Global Dollar, issued by Paxos Digital Singapore, MAS-regulated, 1:1 USD redeemable,
natively on Robinhood Chain (`app/design/PILL-FACTS.md` line 6). `approvedPairTokens(USDG)`
is `true` on the Pons factory.

### Pons V2 (external, not built by this project)

| Contract | Address |
|---|---|
| Pons V2 launch factory | `0x7eD598BcEf8bd9Edd8C97A195C6d13f40801EC7e` |
| Pons V2 fee escrow | `0xd3AFEB2a57f70eF218Aa82451c51B2fb0416Ac9e` |
| Pons V2 meme hook | `0xE5e702641Ea86F4ae6cC3cDaeD2B886f976Be044` |

Source: .
`launchFee` was `0.0005 ETH`; `maxCreatorTaxBps` was `1000`; the launch-second anti-snipe
tax is `9,900` bps (99%) decaying to zero over 3 seconds. Re-read these live before relying
on any of them; Pons is an external protocol XLINK does not control.

### The retired v1 factory, and why it is retired

| Contract | Address | Deploy block | Deploy tx |
|---|---|---|---|
| `HandleVaultFactory` (v1) | `0x1594B1BA75B793117003E70B2903E8BAECC4eCeD` | 59,661,960 | `0x2be115d3f49cad8dbefc8f30804a05adcd7d3e674cd046e4d0056dadcc3f5de0` |
| `HandleVault` implementation (v1) | `0x416B8CAC08FdD0e109C3591243502914C5823808` | 59,661,960 | (same tx; v1's constructor deployed both in one transaction) |

Source: the deploy broadcast,
 lines 132 to 133 ("the RETIRED v1 factory"), .

The v1 factory paired only against native ETH, used a single flat `platformBps` taken as a
plain percentage of every claimed delta with no floor formula, a fixed 24-hour
`RELEASE_DELAY` constant instead of a per-vault configurable window, allowed exactly one
launch per vault ever, and had no launch tickets (only an allowlisted launcher could create a
vault or launch a coin at all) and no community delivery path. It is what
. It was superseded by "Fee model v2" (USDG-only
pairs, the floor and split formula described above, a per-vault first-bind window, handle
cooldowns, auto-release, community delivery, and oracle-signed launch tickets that let the
general public launch without being on an allowlist; 
which v2.1 in turn replaced with the one-shot claim, no cooldown, no threshold, reflections
and the abandoned-pot sweep described in this document. **One vault still lives under the
retired v1 factory**: an E2E test coin under XLINK's own house handle, created 2026-09-10
before v2 existed, and distinct from the real, official $XL, which later launched on the
v2.1 factory under the same X account's renamed handle (see the "Links and addresses" table
above)
(vault `0xa75b74d833B03f2eb477873090FC4a0628A13AE8`, for X user id `2098113645448249347`,
handle `xcoinpad`). It was never migrated, because a vault's factory is fixed at creation.
's vault cache is scoped by factory address, but when the same handle has a vault
on both factories the cache's own "v2 wins a clash" merge rule drops the older row entirely
instead of showing both: as of 2026-09-12, `GET /vaults` lists only the v2 `xcoinpad` vault
created below and omits this real, funded v1 `xcoinpad` test vault .
The v2
factory's own first `VaultCreated` event fired 2026-09-12: a fresh, non-allowlisted wallet
exercised the public launch-ticket path end to end, creating a second vault for the same
handle, `xcoinpad` (vault `0x981830a74e2a74c28579c9a95e1bc40311690f9e`, token "XLINK Test
Coin" / `XLT` at `0x86a9929058e5A37Cf1639B279fE5b81dc357C081`), confirmed live on chain
(`eth_getCode` returns a 45-byte EIP-1167 clone of the v2 `HandleVault` implementation) and
in `GET /vaults` . It was a controlled test of
the launch mechanism, not an outside handle launching its own coin: on the v1 and v2 factories
the only handle with a coin is XLINK's own test handle `xcoinpad`. Outside handles have since
launched on v2.1 (see "Known limitations and open items"). The real, official $XL later
launched on v2.1 under the same account's renamed handle, `xlinkmoney` (see "Links and
addresses" above).

## The trust model

What the identity oracle can and cannot do. The oracle is the one real, unavoidable trust
dependency in this system, and in v2.1 it carries more weight than in v2: its signature on an
`Attestation` is the sole on-chain authorization for a claim, and a claim pays the whole pot
to the `to` address the attestation names, immediately (`contracts/src/v21/HandleVaultV21.sol:543`).
There is no longer a contest window or a re-bind delay between a signature and a payout. The
compensating controls are therefore all around the key: it is never held by a person or in
application memory and lives only inside a Cloudflare Worker, `signer.xl.money`, which holds
the oracle key as a Worker secret, only answers callers on an IP allowlist, requires a
proof of the X sign-in bound to the `to` wallet before it will sign, authenticates every
`/sign` call with an HMAC over the raw request body plus nonce replay protection and a rate
limit, and fails closed (``, ``,
; `reports/security/CUTOVER-v21-2026-09-13.md` section 1,
`proof_enforced:true`, `caller_gating:"ip"`). On chain, an attestation is single-use (a
per-vault `claimNonce`), expires at its signed deadline, may not be dated more than one hour
out (`MAX_ATTESTATION_TTL`), and is tied to the current `oracleEpoch`, so the guardian's
instant `revokeOracle` invalidates every outstanding attestation in one transaction
(`contracts/src/v21/HandleVaultV21.sol:130,171,543-570`; proven by
`test_ec14_guardianRevokeOracle_invalidatesAttestation`). A compromised oracle key, for as
long as it went unrevoked, could sign a claim to an attacker's address for any launched pot
with a balance; that is the honest statement of the residual risk, and it is why the signer
hardening rounds and the key-custody checklist exist.

What only the handle's owner can do. Claim, and nothing else: there are no owner-only
settings left on a v2.1 vault (`setAutoReleaseThreshold`, `optInDelivery`,
`optInConversion`, `updatePayoutAddress` and `release` were all removed,
`contracts/src/v21/HandleVaultV21.sol:18-58`). "Owner" is not stored on chain at all;
`owner` returns the zero address for every v2.1 vault (`:581`). Ownership is proven fresh
at each claim by the X sign-in behind the attestation.

The oracle and launch tickets. Two different EIP-712 structures are signed by the same
oracle key: an `Attestation` (identity binding, verified against a specific vault's own
domain) and a `LaunchTicket` (permission to create a vault or launch a coin, verified
against either the factory's domain, for vault creation, or a specific vault's own domain,
for launching a coin). A `LaunchTicket` names the exact `(handleHash, xUserId, launcher)` it
authorizes, expires at a signed deadline, and is bound on chain to at most one hour of
liveness after the moment it is actually consumed, regardless of how far out its signed
deadline is (`MAX_TICKET_TTL`, `contracts/src/v21/HandleVaultV21.sol:125`,
`contracts/src/v21/HandleVaultFactoryV21.sol:180`; the real staleness control is the signer's own
issuance discipline, a 10-minute issuance default in 
 and a 30-minute hard cap enforced inside the Worker
(``)).

The delivery operator. Only `factory.deliveryOperator`, today XLINK's gas-only keeper
key `0xE585d13afDA7383A59fCF6406c6dEDFa257f7591`, may call `executeDelivery`. It can only
ever move a requested vault's available balance to the delivery wallet snapshotted at request
time, minus the snapshotted fee to the platform treasury; it cannot choose a different
destination, cannot execute without a prior `requestDelivery`, and cannot execute before
the snapshotted `deliveryEta` (`contracts/src/v21/HandleVaultV21.sol:634`).

The guardian. `revokeOracle` is instant, one transaction, zeroes the oracle for every
vault simultaneously; appointing a new oracle is owner-only and behind a 7-day timelock,
deliberately asymmetric (kill fast, appoint slow and in public)
(`contracts/src/v21/HandleVaultFactoryV21.sol:693,708,715`). The guardian can also
`cancelDelivery` on any vault at any time as an incident brake
(`contracts/src/v21/HandleVaultV21.sol:621`), and `pause` the `ReflectionDistributor` and
any `FeeSplitter`, which also blocks an abandonment sweep from executing while paused
(`contracts/src/v21/ReflectionDistributor.sol:384`; `FeeSplitter.sol:323`).

Every other fund-affecting factory setting (the floor tax and its platform share, the
platform treasury, the delivery wallet, the required pair token, the reflection distributor)
sits behind its own 7-day timelock, propose then execute, so a live change is always public
before it takes effect and never retroactively touches a vault that already locked in its
own terms at launch (;
`contracts/src/v21/HandleVaultFactoryV21.sol:164-179,193`). Two settings are deliberately
instant and owner-only: `deliveryFeeBps` and `deliveryDelay` (a fee change cannot re-price a
request already made, because requests snapshot both), and the two operational roles
`deliveryOperator` and `epochKeeper`. The abandoned-pot path is owner-gated at both its
`markAbandoned` and `executeAbandonment` steps and can be voided by the owner at any time
(`AbandonmentManagerV21.sol:373,539,823`).

The allowlist is for XLINK's own keeper only. `HandleVaultFactory.setAllowedLauncher` and
the two-argument `createVault` overload exist so XLINK's own infrastructure can pre-create
or launch a vault without needing a signed ticket for itself; they are not how a member of
the public gets a vault (`contracts/src/v21/HandleVaultFactoryV21.sol:593,729`).

The launch-ticket public path. Anyone else creates a vault or launches a coin through the
ticket-taking overloads, gated only by a valid, unconsumed, oracle-signed `LaunchTicket`
naming them (`contracts/src/v21/HandleVaultFactoryV21.sol:598`, `contracts/src/v21/HandleVaultV21.sol:297`).
As of 2026-09-12, obtaining a ticket does not require signing in with X at all: connecting a
wallet and signing a short-lived EIP-191 challenge is enough (`GET /launch/challenge`,
`POST /launch/ticket`); X sign-in is required only later, to claim a vault as its owner
(...)"). A prior finding that
described public launching as "invite-only" or allowlisted was wrong and was corrected
.

## Audit history

Three internal review rounds (Phase 1, Phase 2, and a keeper/services review pass) plus six
external audit rounds, five of them by three independent models (DeepSeek V4 Pro, GLM 5.3, Kimi K3) and the sixth by Kimi K3 alone,
each round re-reviewing the actual diff from the previous round's fixes, are recorded in full
in the audit record
proves it) and `contracts/AUDIT-ROUND4-VERIFY.md` (an independent Opus verification pass with
its own proof-of-concept tests for every claimed finding, `contracts/test/Round4PoC.t.sol`).
Summary, oldest to newest:

- **Round 1 to 3 (2026-09-10), pre-v2, fixed contracts on the v1 fee model.** Round 1's
  initial dedupe table alone had thirteen findings; rounds 2 and 3 each raised additional new
  findings of their own as they re-reviewed the actual diff from the previous round's fixes,
  narrowing to one shared residual by round 3. The most severe across all three rounds was
  that a maliciously-attested first bind, inside its own 24-hour window, could not actually be
  undone by a guardian oracle revoke because `release` never re-checked the epoch. Fixed
  with the "sticky contest" mechanism (`bindEpoch` versus the factory's live `oracleEpoch`,
  checked unconditionally until a release has genuinely succeeded once). All three auditors
  converged on this as the one residual after round 2 and confirmed it closed in round 3.
  Verdict: deploy for a five dollar dry run (the audit record.
- **Round 4 (2026-09-11), on the newly-written v2 contracts.** GLM and Kimi independently
  found the same two highs: a coin's fee split could be silently re-priced by relaunching at
  a different tax, and a bound owner's community delivery could bypass the first-bind
  contest window entirely. DeepSeek's first pass returned no answer at all (a reasoning
  budget overflow) and, on retry, agreed with both highs. Sixteen findings total, all fixed
  or explicitly, individually accepted as a documented residual
  (the audit record.md`).
- **A re-check pass over round 4's own fixes** (not the auditors, an Opus verifier reading
  the new source) found four more issues, three of them introduced or left open by round 4's
  own fixes, the most serious being
  that the new handle-correction function could be tricked into stealing a live, already
  bound handle's key rather than only clearing a genuinely abandoned one. Fixed by making
  that function clear-only: it can zero a stale mapping entry, and it can never write a
  destination (the audit record.
- **Round 5 (2026-09-11).** All three auditors independently found that the delivery path's
  bound branch was still missing a pre-launch guard the unbound branch already had.
  DeepSeek separately found that the handle-correction function's own ticket check did not
  tie the ticket to the specific handle it was clearing, meaning a valid ticket for a
  caller's own handle could clear an unrelated vault's mapping. Both fixed; the platform's
  maximum possible share of the floor was also hard-lowered on chain from 5,000 to 2,000
  basis points to make the "never more than 20% of the floor" promise a literal, unbypassable
  ceiling rather than only a constructor default (the audit record.
- **Round 6 (2026-09-11).** Kimi K3 found a regression introduced by two of round 5's own
  fixes: a bound, standing delivery opt-in lost its pinned fee and destination after its
  first successful delivery, so a second delivery on the same opt-in would pay the zero
  address at zero fee, either bricking or burning funds. Fixed at the root (the pinned
  snapshot now survives execution on the bound path; only the unbound, one-shot request path
  clears its own snapshot). This was the last finding before the operator's go to deploy
  (the audit record.
- **v2.1 rounds 3 to 9 (2026-09-12 to 2026-09-13), on the new v2.1 contracts** (vault,
  factory, `FeeSplitter`, `ReflectionDistributor`, `AbandonmentManagerV21`,
  `ReflectionFeeMath`): the same three-model external panel (DeepSeek V4 Pro, GLM 5.3, Kimi
  K3) re-reviewed each round's diff, with an Opus verification pass and a Fable plus Kimi K3
  design duo before the build. Round 13 (the one-shot claim rewrite) closed at external round
  9 with every finding fixed or individually dispositioned (`contracts/audit/v21-r3-*.md`
  through `v21-r9-*.md`, `contracts/audit/v21-r9-disposition.md`; the per-round fix suites are
  `contracts/test/v21/R3Fixes.t.sol` through `R9Fixes.t.sol`). The full suite at deploy was
  351 passing forge tests including a live-fork lifecycle proof against the real Pons
  contracts (`contracts/script/E2E-FORKPROOF-2026-09-13.md`).
- **Every round's instrument is named.** Every "fixed" row in the audit record
  points at a specific fork test that failed before the fix and passes after it; the full
  fork suite (149 tests for the v2 suite at its last recorded run, the audit record
  "Round 6 dispositions"; 351 for the v2.1 suite at deploy) is re-run after every single fix,
  not just at the end.
- **K3 has not reviewed the version of this document, the site copy, or anything built
  after the contract audit rounds above.** Everything in,
  and the app was reviewed by Opus acting as an independent critic (,
  ), not by the external three-model panel; treat that as a lower
  bar of scrutiny than the contracts themselves received.

## The X Money receive flow, as verified

Verified live with a real one-dollar send on 2026-09-12
. Sender side: "You sent $1
to @handle. They're not using this feature yet," a transaction detail screen reading
"Awaiting access to Money," a Cancel button, and a stated 14-day expiry after which an
unaccepted payment refunds automatically. Receiver side, if not already on X Money: "<Sender>
sent you $1, continue before it expires," an Accept button whose acceptance is agreeing to
the Cross River Bank stored value account agreement, then identity verification (legal name
matching a government ID), then the payment reads "+$1," Completed, with the sender's note
shown verbatim underneath, plus a fifteen dollar welcome gift for onboarding during the
current promotion and a native "Share to X" button that opens a composer with a receipt card
(amount, "received from <Sender>," the note, elapsed time, both avatars). There is no
automatic public artifact from X itself; the only public trace is what the receiver chooses
to share, or what XLINK's own bot posts once it independently confirms the send.

**Consequence for product copy:** the sender's own display name and avatar appear on every
screen the receiver sees and on the shared receipt card. During the live test on 2026-09-12 the sender still showed as "Xmemes" with no avatar because the
brand rename was pending; the account has since been renamed to @xLinkMoney with a profile image,
so the receiver now sees the brand name and avatar on every screen and on the receipt card
.

## Eligibility: who gets the X Money delivery option

Every real X handle is launchable, unconditionally
. What differs by handle is
only whether the community "deliver to X Money" option is offered at all, because X Money
itself is a US product. `GET /handles/:handle/profile` derives an advisory
`xMoneyEligibility` of `us`, `non_us`, or `unknown` from an unofficial signal, X's own
"account based in" panel, mirrored (with no authentication and no official support) by
`api.fxtwitter.com`, since the official X API v2 has no country field at all
(). A `us` result shows the delivery option,
live as of 2026-09-13 (the request is submitted on chain, executed by the keeper, bridged to
PYUSD at PayPal by the rail, and finished by the operator's manual X Money send); `non_us`
and `unknown` show it disabled with an explanatory caption. **This gate never touches the launch
path itself**: it only decides whether the X Money delivery button is offered; the on-chain
exit (sign in with X, one-shot `claim` to your own EVM address) works identically for every
handle regardless of country (:
"eligibility must gate only the X Money leg, never the launch").

## What is not automated: the human taps

Three manual steps remain in the actual money path, and are intentionally never scripted:

1. **Selling PYUSD for US dollars inside PayPal.** PayPal has no API for this and no
   auto-convert setting for received crypto .
2. **Moving the resulting US dollar balance from PayPal into X Money**, either by waiting
   for PayPal's own daily automatic transfer or by tapping its instant transfer option.
   PayPal has no self-withdrawal API for a business or consumer account
   (: "NO API for a
   business/consumer account to withdraw its own balance to its own bank").
3. **Sending the X Money peer to peer payment itself, with its note, from the operator's
   phone or the `/ops/pad` console.** There is no X Money API at all
   (: "It has no API and X's ToS bans scripted
   access"). This is also a deliberate product choice, not only a technical limitation: the
   operator has repeatedly rejected scripting or browser-automating the financial apps
   themselves on the brand's own accounts, citing the real risk of PayPal or X freezing a
   KYC'd account for automated access
   (: "browser automation
   of PayPal and device automation of the X app violate their terms and can freeze the KYC'd
   money accounts").

Everything upstream of step 1 (the on-chain delivery execution, the bridge, the swap into
PYUSD) runs unattended now that the gates above are on; no v2.1 on-chain delivery has been
requested or executed as of this writing (the only executed on-chain delivery is the
2026-09-12 v2 test, and the fiat rail was proven standalone on 2026-09-13). Everything from
step 1 onward is, and is meant to stay, a human tap; a WhatsApp alert to the operator fires
per delivery request so the taps happen promptly.

## Known limitations and open items

- **Third-party handles have launched and claimed, but the numbers are launch-day small.**
  The first coin launched through the public site by an outside handle (2026-09-13, with
  reflections on) accrued real fees, split them exactly as the contracts compute, and its
  owner claimed 2.588 USDG with a real X sign in and the keeper-paid one-shot claim; a second
  outside handle's pot exists and is unclaimed. Test artifacts from the build (XLINK's own
  `xcoinpad` vaults and test coins on the v1, v2 and v2.1 factories) are being removed from
  the site's indexes and may still appear in `GET /vaults` while that cleanup lands. Do not
  describe the platform as having broad third-party usage; read `GET /vaults` and
  `GET /activity` fresh instead.
- **The end-to-end pipeline has been proven on the previous (v2) factory; on v2.1 the claim
  leg is proven and the delivery/rail legs are enabled but not yet exercised on-chain. The X
  Money last mile remains a human send each time.** The ten-dollar run was
  the operator personally moving USDG through the bridge and swap into PYUSD, then through
  PayPal to X Money, ending with a real X Money notification reading "You received $9.36 from
  PayPal" .
  On the v2 factory, on 2026-09-12 at 04:19Z, `executeDelivery` ran unattended on a test
  wallet (tx `0xaec5d55e…5285`): 0.029915 USDG left the vault, the delivery wallet received
  0.028420 and the treasury 0.001495, exactly the 5.00% delivery fee .
  On v2.1, the fiat rail was exercised standalone on 2026-09-13 (~9 USDG bridged USDG→PYUSD to
  PayPal's deposit address by the operator), but no on-chain `executeDelivery` has run yet; the
  claim leg was proven the same day by a real handle owner (2.588 USDG paid in one shot, tx
  `0xbc38471d…`).
- **The brand's X account is renamed.** Since 2026-09-12 the brand runs as `@xLinkMoney`
  (https://x.com/xLinkMoney). The v1 `xcoinpad` test vault stays bound to the on-chain handle
  `xcoinpad` forever (a vault's handle is fixed at creation and was never migrated). The
  platform coin has since relaunched on v2.1 under the renamed handle `xlinkmoney`; the
  "Links and addresses" row above carries the live address.
- **`/docs` can briefly disagree with `/llms.txt` and `/llms-full.txt` after a rename or
  relaunch, and neither is guaranteed to match chain state the instant it changes.** `/docs`
  is statically generated (`next build` reports it `○ Static`): its `withLiveConfig` patch
  (`app/src/app/docs/docs-content.ts`) compares the handle and `$XL` address a build was
  configured with against today's known values once, in Node, during that `next build`; it
  never runs at request time, so `/docs` is only as current as its most recent production
  build and deploy. `llms.txt`/`llms-full.txt` are separate static files served
  byte-identical to this document as committed, and only pick up a rename once someone edits
  this file's "Links and addresses" row and re-copies it to `llms-full.txt`. So after a
  rename or relaunch, this file, `/docs`, and `llms.txt`/`llms-full.txt` can each be current
  as of a different moment for a while: this file as of its last edit, `/docs` as of its last
  build and deploy, and `llms.txt`/`llms-full.txt` as of their last copy from this file.
- **The community delivery leg has a real, verified, unresolved regulatory exposure.**
  Converting and sending an unaffiliated handle's own accrued funds to them via X Money, for
  a fee, is money transmission under 31 CFR 1010.100(ff)(5) with no natural-person carve-out
  that comfortably fits recurring, for-profit activity, and 18 U.S.C. 1960 does not require
  knowledge that a license was needed
  . The operator has parked this
  question rather than resolved it, pending the product working end to end first
  . Nothing in
  this document should be read as legal clearance for the delivery leg.
- **The rail executor and delivery automation are enabled and running unsupervised under
  size caps since 2026-09-13.** Per-execution and per-day caps (see the keeper table above),
  a per-request WhatsApp alert, a `DELIVERY_HALT` file that stops execution instantly, and
  the fact that the delivery operator key cannot redirect funds are the controls. Open items
  carried from the enabling review: an unexpected-outbound alert on the delivery wallet
  before aggregate pots exceed about $1k, a reconciliation watch on early real deliveries,
  and moving the delivery key off the box into a policy-constrained signer Worker
  (`ops/delivery-signer/DESIGN.md`). The MSB caveat in the previous bullet is unchanged by
  any of this.
- **The platform coin ($XL) has launched and graduated.** It trades on chain 4663 under
  the token, pot and curve addresses in "Links and addresses" above, and Dexscreener now has
  real pairs indexed for it (XL/USDG on the graduated AMM). Holder count, lifetime trading
  volume and live price are read from the chain and from Dexscreener/hoodscan directly rather
  than quoted here, because those values change continuously and this document does not
  (`app/design/ACTIVITY-DATA-SOURCES.md` section 4, which predates this launch and still
  describes the old test address; it needs its own refresh, tracked separately from this
  document).
- **There is no in-vault ETH-to-USDG conversion in v2.1.** v2's `convertToUSDG` and its
  opt-ins were removed from the vault (`contracts/src/v21/HandleVaultV21.sol:18-58`); the
  factory still carries the timelocked conversion config for layout parity, and
  `conversionEnabled` reads `false`. v2 vaults keep their (disabled-by-default) conversion
  leg.
- **Reflections are live** (see "Reflections: the holders' share, live" under "The fee
  model"). What is still young: the multiplier parameters are the operator's launch-day
  configuration and may be tuned; holder accounting is off chain (balances snapshotted from
  `Transfer` logs each epoch), and the published root is what makes the keeper's allocation
  auditable after the fact, not what prevents a dishonest one; no third-party indexer shows
  reflection payouts yet, so the `ReflectionDistributor`'s `Pushed` / `Claimed` events are the
  source of truth.
- **Abandoned pots.** A pot with no claim, no fee collection on any of its coins and no
  reflection claim on any of its pools for 14 days (`ABANDON_INACTIVITY`) may be marked
  abandoned by the factory owner (`markAbandoned`, an on-chain notice event), which opens a
  14-day public notice window (`ABANDON_NOTICE_WINDOW`); after it the owner may
  `executeAbandonment`, which re-verifies every liveness signal and exact balance snapshots,
  and only then opens a 72-hour drain window (`DRAIN_TTL`) in which the permissionless
  `sweepAbandonedVault` pays the pot to `platformTreasury` and nowhere else, and
  `ReflectionDistributor.sweepAbandonedPool` does the same for that pot's holder pools. A claim,
  a delivery request, any fee activity, a holder's pull-claim, or a one-wei balance change
  voids the mark. This is a genuine privileged drain path and the "non-custodial" framing
  above does not apply to a pot in that state; XLINK will assess abandonment manually from
  its own records and never sweep a pot that shows any activity. No pot has been marked as of
  this writing (`contracts/src/v21/AbandonmentManagerV21.sol:184-186,373,539,647,673`;
  ; read `markAt(vault)` and
  `abandonedFlag(vault)` on the factory live).
- **Two marketing figures on the live home page are explicitly not verified claims.**
  "1M+ users on X" and "100,000+ X Money users" were authorized once by the operator as
  marketing copy for exactly two stat pills and are documented as such precisely so nobody
  mistakes them for sourced numbers elsewhere (`app/design/PILL-FACTS.md`, "Amendment,
  2026-09-12").
- **Where this document and a live `/status` or on-chain read disagree, trust the live
  read.** 
  document can go stale between edits; a chain read or a live endpoint cannot.

## How to verify each claim yourself

```bash
# Confirm the current factory and its live configuration.
F=0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36
RPC=https://rpc.ordofi.network
for fn in "implementation(address)" "oracle(address)" "oracleEpoch(uint256)" \
  "guardian(address)" "owner(address)" "pendingOwner(address)" \
  "platformTreasury(address)" "pendingPlatformTreasury(address)" "pendingPlatformTreasuryEta(uint256)" \
  "deliveryWallet(address)" "deliveryOperator(address)" "epochKeeper(address)" \
  "floorTaxBps(uint16)" "platformShareOfFloorBps(uint16)" \
  "deliveryFeeBps(uint16)" "deliveryDelay(uint256)" \
  "reflectionDistributor(address)" "abandonmentManager(address)" \
  "feeSplitterImplementation(address)" "v2Factory(address)" "requiredPairToken(address)"; do
  echo "$fn: $(cast call $F "$fn" --rpc-url $RPC)"
done
# Expect: implementation 0x810d0a4A0B1d0c787819896C7f9aaB06C36cEd3d,
# reflectionDistributor 0xD5587eaB8C3e44bD8772139B00123f0b65632016,
# abandonmentManager 0xF414fE90210Ff176BBFC38C47e5Fc8d30B2690e0,
# v2Factory 0xcB1C296F4b964cC03Ba89D4414Cf7B9BA1da117b, deliveryFeeBps 500, deliveryDelay 0.

# Count how many vaults exist under v2.1 when you run this.
cast logs --from-block 61581481 --to-block latest \
  --address 0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36 \
  "VaultCreated(uint256,bytes32,address,string)" \
  --rpc-url https://rpc.ordofi.network

# Confirm no pot has been marked abandoned (an empty result means none).
cast logs --from-block 61581481 --to-block latest \
  --address 0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36 \
  "AbandonMarked(address,uint256,uint256)" \
  --rpc-url https://rpc.ordofi.network

# Confirm the live bytecode matches the compiled artifacts (method in contracts/DEPLOYMENTS.md).
cast code 0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36 --rpc-url https://rpc.ordofi.network
cast code 0x810d0a4A0B1d0c787819896C7f9aaB06C36cEd3d --rpc-url https://rpc.ordofi.network
cast code 0xD5587eaB8C3e44bD8772139B00123f0b65632016 --rpc-url https://rpc.ordofi.network

# The previous v2 factory and implementation remain Sourcify exact-match.
curl -s "https://sourcify.dev/server/v2/contract/4663/0xcB1C296F4b964cC03Ba89D4414Cf7B9BA1da117b"
curl -s "https://sourcify.dev/server/v2/contract/4663/0x83bE7A2d8101E3aC87bAA0B5D5b9a0Ca0C67e54D"

# Confirm the claim, delivery and sweep properties on a fork of the live chain.
cd contracts && forge test --match-path "test/v21/*" \
  --match-test "test_claim_fullBalancePayout_pendingPlatformShareReserved|test_ec14_guardianRevokeOracle_invalidatesAttestation|test_sweepAbandonedVault_onlyFactoryCanCallVaultSweep|test_fork_squatPreventionAgainstRealV2Factory"

# Re-run the full v2.1 suite yourself (contracts/README.md "Tests" under "v2.1").
cd contracts && forge test --match-path "test/v21/*"

# Confirm the retired v1 factory and the v1 xcoinpad test vault.
cast call 0xa75b74d833B03f2eb477873090FC4a0628A13AE8 "factory(address)" --rpc-url https://rpc.ordofi.network
# Expect 0x1594B1BA75B793117003E70B2903E8BAECC4eCeD, the retired v1 factory, not the v2.1 address above.

# Confirm services and the signer are live and configured, without any secret in the request.
# (the signer's /health answers only from allowlisted callers; from elsewhere expect 403, which
# is itself the caller-gating working)
curl -s https://api.xl.money/status
curl -s https://signer.xl.money/health

# Read the keeper's view of the live factory (read-only, no signer used). The three env vars
# are the factory address and deploy block from "Contracts and addresses" above plus the same
# public RPC used throughout this document, not secrets; the script has no default and errors
# without them.
HANDLE_VAULT_FACTORY=0x16D36c555Eb5AB96a1159Cbc5B6d9582d3D7eb36 \
FACTORY_DEPLOY_BLOCK=61581481 \
RPC_URL=https://rpc.ordofi.network \
node  --json
```

Every command above reads public chain state or a public endpoint; none requires a key or a
secret. If any answer disagrees with a number in this document, the live answer is correct
and this document is stale on that point.
