Security token development
A token that can refuse.
Permissioned tokens where eligibility is checked inside the transfer path rather than in your signup form. An identity registry behind it, a rule engine configured to your counsel's exemption, and issuer powers split across four roles rather than bundled onto one key.
N° 01The defining decision
The check belongs in the token, not the form
A frontend that hides the transfer button from an ineligible wallet stops nobody. The ABI is public, the RPC endpoint is public, and a direct call skips the interface entirely. That much is uncontroversial. The version that actually decides the architecture is second-order: an approval granted today gets exercised by a contract months later, and the contract exercising it never sees your interface at all.
So eligibility goes inside the transfer path, where issuance, transfer and redemption pass the same gate. The consequence is worth understanding in week one rather than in month nine: every counterparty is a holder as far as the rules are concerned. A pool, a lending market, an escrow contract — if the token can come to rest there, that address has to be on the register, and a person has to have decided it may be. Enforcing in the token is the correct choice and that is what it costs.
What the gate enforces is not our choice to make. The exemption you file under decides which rules bind, and that answer comes from your counsel. We build the engine that takes it, and we say so plainly when a request is a legal question dressed as an engineering one.
N° 02The rule set
Five rule types, one legal input
01
Accreditation
Reg D 506(c) lets you advertise the offering but requires verified accredited status for every purchaser. On-chain that is a flag and a verification date on the identity record, written by whoever performed the check. The contract records an outcome. It does not perform a check, and we will not pretend it does.
02
Holder caps
Two thresholds do most of the work in a US offering: the 100-holder line under the Investment Company Act and the 2,000 record-holder line that pulls an issuer into Exchange Act registration. Which of them binds you, if either, is counsel's answer. The counting is ours, and it is harder than it looks. Our first cut inferred the tally from a balance diff, so a self-transfer registered as a new holder. It now counts one only where the recipient holds nothing and the sender is passing on its whole position — two exact equalities, where an inequality would look safer and be wrong.
03
Jurisdiction allowlists
Reg S is an offshore exemption, so the rule is exclusion rather than admission: US persons out. Country sits on the identity record as a code and the engine reads it on every movement, including the ones that arrive through a venue or an integrator rather than your own interface.
04
Holding periods
Rule 144 style lockups come in two shapes and the cheap one is not always the right one. A single date for the whole offering is what our reference build carries and what one closed raise usually needs. A rolling issuance needs a clock per position, measured from acquisition, so a later purchase does not restart an earlier one and a partial sale does not release a balance that is still locked. That is a storage decision rather than a setting, which makes it cheap at the start and a redeployment afterwards.
05
Concentration limits
A ceiling on any single holder's share of supply. This one is usually a fund or listing requirement rather than a securities rule, and it is the one most likely to reject a legitimate trade. Raising it is a governance action with a record, not a support ticket.
N° 03Standards
ERC-3643 is a decision, not a default
T-REX is the audited reference implementation of the standard, and it is GPL-3.0. For a commercial platform that is a licensing choice to make deliberately with counsel, early, rather than inherit from a dependency someone added in week two and discover during diligence.
ONCHAINID, the identity layer the standard assumes, moves trust rather than removing it. Claims are signed by issuers you have decided to trust, and the set of trusted issuers is still a trust assumption. It is now held on-chain and in public, which is an improvement, but a claim is only worth the diligence behind the signature.
Our reference build is ERC-3643 shaped rather than ERC-3643 compliant, and the difference is worth being exact about: the same three-way split of identity, rules and token with enforcement in the transfer hook, and seven functions matching selector for selector. It also issues and redeems instead of minting and burning, its eligibility check returns a reason string alongside the boolean, the created and destroyed hooks on the compliance interface are absent, three of the seven interfaces the EIP defines have no counterpart at all, and there is nothing playing the part of ONCHAINID. An integrator building against the standard would notice.
An earlier version of that build's own documentation said the contracts were interface-compatible enough for T-REX to drop in. That did not survive being checked, and it is now recorded as a withdrawn claim in the known-issues list rather than edited out of the history. We mention it because this is the specific claim the category is loosest with, and because a buyer has no way to test it from a marketing page.
N° 04Issuer powers
Four powers, four roles
Freeze an account. Move a position without its holder's signature. Issue supply. Halt the market. To anyone arriving from DeFi each of those reads as a backdoor, and each is ordinary machinery for a regulated instrument: registers get corrected, orders get served, and keys get lost by people who still own what the key controlled.
The flaw is never that the powers exist. It is bundling them onto one key. In the reference build they are four separate roles — issue and redeem, freeze, pause, recover — drawn so the blast radii differ: the role that can move one holder's position cannot print supply, and the role that can stop every transfer in the system cannot move anything at all.
Being four roles is not the same as being four signers, and the paragraph above is the sort of sentence that quietly implies otherwise. On our own testnet deployment all four sit on one key, which is written down in the known-issues list as a demonstration rather than a posture. Distributing them, and putting the ones that matter behind a multisig with its own threshold, is a deployment decision — the first one we would argue about before anything went to mainnet.
The powers are bounded, and the bound is the part worth testing rather than asserting. A forced transfer overrides timing, not eligibility: the recipient still clears every active rule, so an ordered move cannot land a position with an unaccredited holder or inside a barred jurisdiction. Our first version got exactly this wrong — the override confirmed the recipient was KYC verified and skipped accreditation, jurisdiction and the concentration cap — which is why both privileged paths now run through the same eligibility function an ordinary transfer uses. Administration itself moves by announcement and a three-day wait, so holders see a change of controller before it takes effect rather than after.
N° 05The dry run
Tell the buyer why, before the gas
A transfer that reverts with nothing readable teaches a buyer only that something is wrong. So the rule engine exposes a read-only check returning both a verdict and a reason. Not accredited. Country not permitted. Locked until this date. Holder cap reached. The interface calls it before anyone signs anything.
Writing that is easy. Keeping it honest is not. A dry run that disagrees with the transfer hook is worse than no dry run at all, because it produces confident wrong answers: a buyer told they are eligible, a transaction that reverts anyway, and a support queue growing in the gap between two implementations of the same rule. The check and the hook have to read the same code, not merely agree at the time someone wrote them.
Ours got this wrong once, in the safer of the two directions. The check reported every issuance as blocked for insufficient unfrozen balance, because it evaluated a balance rule against the sender and an issuance sends from address zero, which holds nothing. The hook was right. The preview was wrong, and wrong in the direction that turns business away rather than the direction that promises a transfer the chain then refuses — which is why it is logged as low severity and not as something worse. It was still enough to make the subscription flow look broken to every buyer who reached it. Adversarial review found it, the fix carries a regression test, and it sits in the same defect list as the rest rather than being dropped from the history.
Investment
Fixed scope. No drift.
From $45,000 — token, identity registry, rule engine and issuer console.
- Permissioned token with eligibility enforced in the transfer hook
- Identity registry with country, accreditation, expiry and sanctions state
- Rule engine configured to your counsel's exemption
- Read-only eligibility check that reads the same code as the hook
- Issuer powers split across four roles, ready for separate signers
- Documented invariants with stateful fuzz testing
- Static analysis and linting gating CI
- Specification, role matrix, threat model and known-issues list
- Testnet deployment with verified source
- Announced role handover to your multisig
- 30-day defect warranty
Questions
The answers we give most often.
- What makes a token a security token rather than an ERC-20 with a whitelist?
- The enforcement point, and what stands behind it. A whitelist bolted onto a standard ERC-20 usually lives in the interface or in an approval step, which means the token itself will still move for anyone who calls it directly. A security token puts the ruleset inside the transfer path, so issuance, transfer and redemption clear the same gate, with an identity record behind it carrying country, accreditation status, KYC expiry and sanctions state. It also carries the powers a regulated instrument needs: freeze, forced transfer, recovery. If the token cannot refuse a transfer on its own, your compliance story is a policy document rather than a control.
- Should we use ERC-3643?
- It comes down to who you have to interoperate with. If your transfer agent, a venue you want to list on, or an investor's custody provider expects the standard, implement it exactly and settle the T-REX licensing question with counsel before the build rather than during diligence. If none of them expect it, a shaped design gives you the same separation of identity, rules and token without the obligation. The part usually underestimated is what the second choice costs later: going from shaped to actual is a migration rather than a swap, because the gap that matters is the missing interfaces and the absent claim layer, not the function names that already line up. Decide it while the holder list is short. What we will not do is describe something as compliant because it is shaped like the standard.
- Can holders trade freely once they hold the token?
- Only within what the rule engine permits, and that is the point of the instrument. Every movement re-evaluates both sides, so a holder whose verification has lapsed or who has moved to a restricted country cannot pass a position on. The harder constraint is not the contract, though. Secondary liquidity for permissioned tokens is thin, the venues that will list them are few, and the same rules that make the instrument lawful are what make an ordinary market maker decline it — any address that holds the token has to be on the register, including a pool's. The contract lets a trade happen. It does not produce a counterparty, and the exit route is worth writing down before the raise rather than after it.
- What happens when a holder's KYC expires?
- The identity record carries an expiry date, the transfer hook reads it, and an expired holder stops being able to send or receive. They keep the position, because expiry suspends transferability rather than confiscating anything. Income is the part that surprises people. The entitlement is already fixed in the balance history and does not move, but drawing it down requires current standing, so an expired holder cannot claim until they re-verify. That is the same rule that stops a frozen or sanctioned wallet collecting income, and it cannot be written to apply to one and not the other. Which makes re-verification an operations problem: a prompt several weeks ahead, not a surprise on the day, so the console needs a view of who is about to lapse. That is an indexing job rather than a contract one, because a permissioned token deliberately never enumerates its holders.
- Can the rules change after launch?
- Configuration can, and it is designed to. Which rules are active, the numbers inside them, the country list, the lockup date: all adjustable by a role, because exemptions change and a raise that grows past a threshold should not need a redeployment. That adjustability is also the sharpest edge in the design, and our own build still has it unguarded — one call from the rules role can switch every restriction off at once. Putting that behind a timelock and a multisig is on our open-work list rather than presented as solved, and it is a launch requirement rather than a nicety. The shape of the rule set is a separate question. Adding a rule type the engine was never built to evaluate, or tightening a token that shipped with a permissive transfer path, means a new deployment and a migration of every holder — a governance event with a legal component attached, which is why we would rather over-build the engine at the start than negotiate it later.
- Do we need a transfer agent?
- Often, and whether you do is a question for counsel rather than for us. Where an agent is involved, the official register is the one they maintain, and your on-chain balances are authoritative only to the extent that arrangement says they are — a governance fact rather than a technical one, and one that no amount of contract correctness settles. What it changes on our side is concrete: the agent needs an export they can reconcile against, a defined path for corrections that leaves a record, and an issuer console that logs who did what and when. We build for that pattern. We do not act as a transfer agent, and we do not tell you whether you need one.
Next step
A rule your interface enforces is a rule anyone can route around.
Tell us the instrument, the jurisdictions your holders sit in, and which exemption counsel is working toward.
