A specimen. No company, no shares, no value.
The legend on your share certificate, enforced by the token.
CapRail keeps a private company’s cap table on Solana. Who may receive its shares is checked by the token itself — a Token-2022 mint with a transfer hook — on every transfer, whichever app sends it. A transfer that fails the check does not happen.
Restrictive legend
- 1. These shares may be transferred only to a holder admitted by the company’s compliance officer. Enforced. The hook refuses NotAccredited. Since v0.1.0.
- 2. An admission that has expired or been revoked admits nothing. Enforced. AccreditationExpired; the next transfer after a revocation is refused.
- 3. Shares not yet vested may not be transferred. Not yet. Vesting arrives with v0.3.0.
- 4. The company has a right of first refusal on any sale. Not yet. ROFR arrives with v0.4.0; until then the policy refuses to switch it on.
Devnet demo. Admission statuses are set by the compliance officer inside the product; there is no external KYC.
On paper, the legend is a promise. In CapRail, it is a check.
Before
The shareholders’ agreement says “admitted investors only”. The certificate prints it. A wallet can still send the token to anyone, and the company finds out afterwards — if it finds out at all.
After
The policy is data the token reads on every transfer. A transfer to a wallet the company has not admitted is refused by the network; balances on both sides stay as they were, and the refusal is in the company’s journal with its reason.
Reverse · Transfer register
Five transactions on Solana devnet, 3 October 2026, from one run of the demo through the hosted panel. Each opens in the public explorer.
| When (UTC) | Entry | Shares | Outcome | Signature | |
|---|---|---|---|---|---|
| 14:37:49 | Treasury → alice, distribution | 100,000 DEMO | settled | WnYV…puUV | |
| 14:37:55 | alice → bob, both admitted | 10 DEMO | settled | 4k1m…zqkV | |
| 14:38:01 | alice → a wallet nobody admitted | 10 DEMO | REFUSEDNotAccredited | 3R5A…mtwk | |
| 14:38:19 | alice → bob, an accepted offer: 1.25 dUSD per share, fee 1.875 dUSD out of 187.5 paid | 150 DEMO | settled · trade | 2ui7…ARqb | |
| 14:38:25 | A buyer whose admission was revoked tries the same offer | — | REFUSEDNotAccredited | 2Fqy…5mcw |
“alice”, “bob”: disposable keys of the demo. The refused transactions were sent without the wallet’s simulation on purpose, so that the refusal is recorded on chain for anyone to see; a wallet that simulates first stops before signing, and the panel records that refusal as “simulation”.
What it does
Admission is a property of the token
A compliance officer admits a wallet, with an expiry. The token’s transfer hook reads that record on every transfer and refuses anything else. A changed policy or status applies to the next transfer — no reissue, nothing for holders to do.
The cap table is read from the chain
Holders, amounts and shares of the issue update from the transactions themselves; every attempt, settled or refused, is in the company’s journal with its reason, time and parties.
A market that checks the buyer first
A holder offers shares at a fixed price; only wallets that would pass admission see the offer. Shares and payment move in one transaction, or neither does, and the platform fee is shown before accepting.
Measured
| What | Budget | Measured | Where, when | |
|---|---|---|---|---|
| Transfers to a non-admitted wallet refused, balances unchanged | 100 of 100 | 100 of 100 | devnet, v0.1.0, Sep 2026 | |
| Transfers between admitted investors pass first time | ≥ 99 of 100 | 100 of 100 | devnet, v0.1.0, Sep 2026 | |
| Cap table shows a confirmed transfer (p95) | ≤ 5 s | 0.74 s | hosted panel on devnet, 20 transfers, 3 Oct 2026 | |
| Refusal in the journal with its reason (p95) | ≤ 5 s | 0.80 s | same run | |
| Whole demo, company to updated cap table | ≤ 3 min | 22.6 s | same run | |
| Network fee of a compliant transfer, for the sender | ≤ 0.001 SOL | 0.000005 SOL | devnet, 20 transfers, 3 Oct 2026 | |
| Trades where one side moved without the other | 0 of 100, 20 broken on purpose | 0 | program tests | |
| Offers matched to non-admitted buyers | 0 of 200 | 0 | program tests | |
| Not measured yet: vesting (v0.3.0), the period report (v0.5.0) | — |
What CapRail does not do
- It does not verify anyone’s accreditation. The compliance officer sets admission inside the product; there is no KYC or KYB provider, and the demo does not prove that a status matches a real person.
- It does not issue or sell shares, or wrap them legally. No offering, no SPV, no shareholders’ agreement, no trading-venue licence. It enforces rules the company has already agreed.
- It does not enforce vesting or a right of first refusal yet (v0.3.0, v0.4.0), and it does not produce the period report yet (v0.5.0). Jurisdiction and investor type are recorded, not enforced.
- It does not hold your shares. An offer is a delegation, not escrow: a seller who moves the shares away leaves the offer standing, and the market marks it stale with the reason.
- It runs on Solana devnet only. The payment token is a demo stablecoin, not USDC.
- Not every wallet can send these tokens yet. A wallet that does not add the transfer hook’s accounts fails before the check runs — nothing moves, but nothing is sent either.
Questions
- What stops someone from sending the token outside your app?
- Nothing in the app — the check is in the token. Token-2022 calls the transfer hook on every transfer of this mint, from any program or wallet.
- Who decides who is admitted?
- The company’s compliance officer, with their own key. The administrator cannot change admission statuses.
- Can I bring a token I already issued?
- No. The policy is attached when the token is created; tokens issued elsewhere are out of scope.
- Is this on mainnet?
- No. Everything runs on Solana devnet; going to mainnet is a separate decision.