Build a hook, a companion, or both as a pair
Write a hook or a companion with your own AI coding agent: a hook that runs on every trade, a companion that spends the companion fee, or both as a pair. Deploy it yourself on the open standard, or submit its source to the Workshop: Bordrless checks it, builds it and deploys it, and you can earn a share of every launch someone else makes with it.
Two routes#
- Your own
- The standard is open: write a custom hook against the
bordrless-hookcrate, deploy it yourself, make it immutable, and put it on a mint of your own, a pool of your own, or a launch on Bordrless from a config you make (prepared for the mint withtemplateHook.prepare, made withbuildCreateConfig; the SDK’s README walks the whole terminal flow). A companion the same way: deploy the script, make it immutable, and launch with it through the SDK or the API; the companion program runs an immutable script with no approval. The one rule, the programs’: a hook or a script that runs here is immutable, behind the public hook timelock (3 days or more), or upgradeable only by Bordrless. On bordrless.app such a program is not read by Bordrless: the token shows it as a custom hook written by its creator, with who can upgrade it and no reading, and it is not in the Workshop. Unless you ask for the reading: submit its source with the program’s address on the same submit page, pay the same fee, and once Bordrless’s build of your source matches the code on chain, its reading shows wherever the program is used. A launch whose creator fee goes to a program of your own, not the companion program, is allowed by the chain and hidden on the site. Write a hook and build on Bordrless cover it. - The Workshop
- This walkthrough. You submit the source, never a deploy. Bordrless checks it, approves it and deploys it under its own upgrade key; you pay what the deploy costs. It is listed, launchers pick it on the launch page, the site shows Bordrless’s reading of it (its rules as exact rows, the most it takes, what to watch) wherever a launcher or a buyer meets it, and you earn the share you choose of every launch someone else makes with it: a hook’s builder 0% to 50% of the creator fee, in 5% steps; a companion’s or a pair’s 50% of the launcher’s part of the creator fee, or nothing.
What you can build#
A custom hook on the trades
Today- Runs
- On every transfer of the token. A buy is a transfer out of the pool, a sell one into it.
- Can
- Take a cut, keep state in each holding, refuse a transfer.
- Limits
- It never gets anyone’s signature and calls no other program: the token program applies its answer, never more than the amount.
A companion
Today- Runs
- On a timer, every 10 s to 1 day, on the companion program, on chain: it holds the launch’s companion fee as a pot and calls your code.
- Can
- Spend the pot the companion fee fills: market making, buybacks, games.
- Limits
- The companion program holds the funds: your code spends the pot and nothing else, leaves the dev’s tokens alone, and never gets anyone’s signature but the companion address’s.
Both, as a pair
Today- Runs
- The hook on every transfer, the companion on the timer. One item in the Workshop, one approval, one config.
- Can
- The hook takes a cut, keeps a score or funds the pot; the companion pays from the pot, filled by the companion fee, by the hook, or both.
- Limits
- The hook records, the companion reads and pays; neither reaches the other’s code. The config requires both, so a launch gets both or neither.
The Workshop takes hooks, companions, and both as a pair. It takes no game drawn at random: a draw needs an oracle the companion pays for, so that is the built-in Jackpot’s on Bordrless’s own lottery hook.
Two layers, then. A hook on the trades is your program inside the trade: the token program calls it before and after every transfer, mint and burn and applies its answer, so it takes cuts, refuses, and writes what it wants into each holding; it never holds money. A companion is your program too, a script, but it never runs inside a trade: Bordrless’s companion program holds the launch’s companion fee in a pot and calls your script on a timer with the launch’s accounts (the mint, the launch, the companion, the pool, your state, then whatever the sender passes); your script reads whatever it likes, its hook’s data in the holdings, the pool, its own state, and answers by acting as the companion address, and Bordrless’s program executes that inside hard bounds: a trade on the launch pool, a buyback, a burn, a payout to holders or wallets within the launch’s payout terms, never more than the pot, never the dev’s tokens, never the companion address’s rent. Bordrless’s program is never upgraded for a builder’s program, only for a new kind of action.
A pair: a hook and its companion as one#
A hook on the trades and a companion on the pot, as one. The hook can take a cut, keep a score or fund the pot; the companion pays from the pot, filled by the companion fee, by the hook, or both. A pair is built as two programs and shipped as one thing. They talk one way, hook to companion:
- The hook writes
- Per holder, the 64 bytes of hook data in each holding, answered from
before_transferand written by the token program with the balances. Per mint, its own state at["state", mint]. The aggregate goes in the state (a total, a last buyer, the period), the per-holder facts in the hook data (what they held when the period began, when they last sent). - The companion reads
- In its step it asks for the hook’s state and the holdings it pays (its
keeper.jsonsays which ones Bordrless’s keeper brings), verifies each against its hook data, pays from the pot in SOL (lamports to the holder’s wallet on a native coin), or answers a payout the companion pays and the hook records, and keeps what it paid in its own state so nothing is paid twice. It can never write hook data; the hook can never pay. - No randomness
- A step has no payer for an oracle, and a slot or a clock a trader can time is not random. A pair pays by what the hook recorded: the last buyer, the longest holder, who is down. A drawn-at-random game is the built-in Jackpot.
- One address
- The config made from a pair names the hook and requires the companion. A launch with it gets both or neither, and the launch page locks the hook picker to it.
Four patterns#
What each one ships, what Bordrless’s keeper needs from it, and what its card reads once the reading is in.
- A token tax that funds the pot
- The shape of Whale Bait, the first pair. The hook cuts whale trades in tokens (3% from 5M tokens, 5% from 10M, 8% from 20M) into the companion address’s holding; sends are free; each holding’s hook data keeps the epoch it was last paid in. The companion sells what the hook collected into the pot and pays every holder under 20M tokens once a 5-minute epoch, in SOL to their wallet. Ships the hook’s
src/lib.rs, the companion’ssrc/lib.rsand itskeeper.json(holders under 20M whose stamp is not this epoch,payTo: owner, three a step beside the swap accounts). The card reads: Under 5M tokens: 0% hook tax · 5M–10M tokens: 3% of the tokens on buys and sells, to the pot · 10M–20M tokens: 5% · 20M+ tokens: 8% · Transfers: free · Every 5 minutes: the pot pays holders under 20M tokens. - A score and a game
- The hook writes each holder’s score into its hook data (held since when, what was bought, a streak) and the aggregate into its state. The companion pays the leaders from the pot the companion fee fills, once a period, and marks who it paid. Ships both
src/lib.rsand akeeper.jsonthat filters holdings on the score’s field. The card reads the score’s rules on buys, sells and transfers, then what each step pays, to whom and how often. - A SOL cut
- The hook implements
quote_cut, the launchpad’s callback, and shipshook.jsonwith its caps (1 to 10% of a buy’s SOL, 0 to 10% of a sell’s); the launchpad takes the cut as the hook’s own fee, on top of the launch’s, and on a pair it lands whole in the pot. Shipssrc/lib.rsandhook.json; the trading test runs the cut at the caps. The card reads the rate of the SOL on buys and sells, to the pot. - A payout through the companion
- Lossback’s path. The hook keeps a record in the hook data (an entry price, what was paid) and has
record_payout, which only the companion’s payout authority may sign. The companion’s step answers aPayoutAnswernaming holdings among its accounts; the companion pays each owner from the pot within the terms and has the hook record it. Ships bothsrc/lib.rsand akeeper.jsonwithpayouts: true,payTo: owner. The script is made withcreate_script_v2(companion.createScriptV2in the SDK). A launch from the site makes it with open terms (a step may pay the whole pot) unless itskeeper.jsonsetspayoutTerms; the launch’s beneficiary or the script approver can change them after launch (companion.setPayoutTerms).
The template and its rules#
A hook is one Anchor program on Bordrless’s template. You write its Rust files under src/; the Cargo.toml and the crates are the builder’s, so a hook adds no crate of its own. To build and test it on your machine, use the builder’s Cargo.toml with its two crates from the public programs repository:
# Bordrless's hook template, for a build on your machine: the builder's Cargo.toml, with
# its two crates from the public programs repository. The builder uses its own copy and lock.
[workspace]
members = ["."]
[package]
name = "my-hook"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
crate-type = ["cdylib", "lib"]
name = "my_hook"
[features]
default = []
cpi = ["no-entrypoint"]
no-entrypoint = []
no-log-ix-name = []
idl-build = ["anchor-lang/idl-build", "bordrless-hook/idl-build", "bordrless-game/idl-build"]
anchor-debug = []
custom-heap = []
custom-panic = []
[dependencies]
anchor-lang = "=1.2.0"
bordrless-hook = { git = "https://github.com/BordrlessDex/bordrless-programs" }
bordrless-game = { git = "https://github.com/BordrlessDex/bordrless-programs" }
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
[profile.release]
overflow-checks = true
lto = "fat"
codegen-units = 1
[profile.release.build-override]
opt-level = 3
incremental = false
codegen-units = 1The rules, checked on your files before anything else:
- Its files
- Rust files under
src/with lower-case names: at most 8 files and 120 kB in all.src/lib.rsis the program. - No calls
- It calls no other program. It acts only through its answers to the token program.
- No SOL
- It moves no SOL, and closes or resizes no account.
- Plain Rust
- No unsafe code, no inline assembly, no macros of its own, and nothing read from the build machine (
include_*!,env!,option_env!,#[path]). - Its id
- One
declare_id!and one#[program]module. The builder writes the program id Bordrless reserves for it. prepare- The standard one: no arguments; accounts payer, mint, state at
["state", mint], registry, system program. The launch sends it for each new mint. - Its registry
- The extra accounts every callback gets: only the hook’s own and the mint’s, at most 4, written once by prepare.
- Beside src/
keeper.jsonfor a companion that pays holders: which holdings each step brings and how often a step runs;mintWritablepasses the coin’s mint writable in every step, which any burn needs (without it a burn fails the whole step, and a burn never reaches the dev bag);payoutTermssets the payout terms, open (a step may pay the whole pot) without it.hook.jsonfor a hook with a SOL cut: its caps. Both are checked at submission and bound by the approval.
A companion builds on a template of its own, since it trades on the DEX and so can’t keep the rule against calling other programs. Its brief holds that template’s Cargo.toml.
1. Give your agent the brief#
Open an empty folder in Claude Code, Cursor or any coding agent and paste the brief for what you are building. It holds the template, every rule the checks hold it to and how to test it, and it tells your agent never to deploy anything: on this route, Bordrless deploys.
You are helping me write a token hook for Bordrless and submit its source to the Bordrless
Workshop. I write and test the code on my machine; Bordrless checks it, builds it and deploys it.
Never deploy anything to mainnet. Read every rule below before writing code.
BORDRLESS: a token standard of its own on Solana, not SPL and not Token-2022, with its own DEX and
launchpad. Its token program calls a mint's hook before and after every transfer, mint and burn,
and applies what the hook answers. Trades are transfers: a buy is a transfer out of the pool's
vault, a sell is one into it. So a hook can take a cut of trades, keep state in each holding and
refuse a transfer.
PROGRAM IDS (the same on mainnet, devnet and localnet):
token 2XoEWp8cF3kRXg74eVwPAyTFhVCAztn3V88komxAvr22
DEX GyzKSnnEu2uN5bBRecE4XYY2enbfR2D2MtxnbJPGy7hk
launchpad 1jcBymHxBjniZDhNPy51Vgm5Nz7pLUdxa9UBHc4TavC
quote A49oVhX22ExMwTEtFC6Y8nhBdZ4LJDGhdXLDn4c2f59i (every launch's quote_mint: native SOL,
lamports, since 15 Oct 2026; bridged SOL on coins launched before)
THE TEMPLATE: a Workshop hook is one Anchor 1.2 program on Bordrless's template. I send only
the Rust files under src/ (src/lib.rs is the program; lower-case names;
at most 8 files and 120 kB in all); the Cargo.toml, its lock and the crates are the
builder's, so add no crate. On my machine, build with this Cargo.toml (the builder's, with its
two crates from the public programs repo):
# Bordrless's hook template, for a build on your machine: the builder's Cargo.toml, with
# its two crates from the public programs repository. The builder uses its own copy and lock.
[workspace]
members = ["."]
[package]
name = "my-hook"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
crate-type = ["cdylib", "lib"]
name = "my_hook"
[features]
default = []
cpi = ["no-entrypoint"]
no-entrypoint = []
no-log-ix-name = []
idl-build = ["anchor-lang/idl-build", "bordrless-hook/idl-build", "bordrless-game/idl-build"]
anchor-debug = []
custom-heap = []
custom-panic = []
[dependencies]
anchor-lang = "=1.2.0"
bordrless-hook = { git = "https://github.com/BordrlessDex/bordrless-programs" }
bordrless-game = { git = "https://github.com/BordrlessDex/bordrless-programs" }
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
[profile.release]
overflow-checks = true
lto = "fat"
codegen-units = 1
[profile.release.build-override]
opt-level = 3
incremental = false
codegen-units = 1
Read crates/bordrless-hook/src/lib.rs in https://github.com/BordrlessDex/bordrless-programs before
guessing an API (not its authority module: the builder's copy of the crate has none). There,
programs/tax_hook shows cuts. The Workshop takes no game hooks (a jackpot or a streak): their
pots need the companion's own game checks. For TypeScript tests:
npm install @bordrless/sdk @bordrless/shared
(the SDK's source: https://github.com/BordrlessDex/bordrless-sdk).
CALLBACKS: before_transfer, after_transfer, before_mint, after_mint, before_burn, after_burn. Each
is an instruction named after it taking TokenHookArgs (amount, source_owner, destination_owner,
the balances, the supply, both holdings' hook data). Accounts: five fixed ones (hook signer, mint,
source, destination, authority), then the extras the registry lists. Every callback first runs
one check_call(&ctx, &args): the hook signer signs and is PDA(["hook-authority", hook], token
program) (hook_signer in the crate), and args.mint is the mint the hook's state was prepared for.
A before_* callback returns, in its return data:
pub struct HookReturn {
pub deltas: Vec<Delta>, // up to 3 cuts { amount: u64, account: u8 }
pub burn: u64, // pool hooks only: 0
pub lp_fee_bps: Option<u16>, // pool hooks only: None
pub source_hook_data: Option<[u8; 64]>, // the holding's 64 bytes of state
pub destination_hook_data: Option<[u8; 64]>,
}
Each cut goes to a writable holding of the mint the registry lists (account = its index in the
callback's accounts); together they never exceed the amount. An error refuses the transfer. A hook
never gets a user's signature and never moves tokens itself: the token program applies its answer.
BUYS AND SELLS: the launch account PDA(["launch", mint], launchpad) names its pool (Launch.pool):
a buy is a transfer whose source_owner is that pool, a sell one whose destination_owner is.
FLAGS (TOKEN_HOOK_FLAGS, a u16 the launch config carries):
BEFORE_TRANSFER=1 AFTER_TRANSFER=2 BEFORE_MINT=4 AFTER_MINT=8 BEFORE_BURN=16 AFTER_BURN=32
TRANSFER_RETURNS_DELTA=64: before_transfer may answer cuts
WRITES_HOOK_DATA=128: before_* callbacks may answer the 64 bytes
Bordrless reads them from the source, never by hand: a callback is on when its body does more than
check_call(&ctx, &args)?; Ok(HookReturn::default()) (an after_* one: check_call(&ctx, &args)); cuts
when before_transfer builds a Delta; hook data when the code sets source_hook_data or
destination_hook_data. An answer its flags don't allow is refused whole (UnsupportedHookReturn).
A cut on every transfer is BEFORE_TRANSFER | TRANSFER_RETURNS_DELTA = 65.
THE RULES (checked on the source before anything else; one broken stops it):
- Calls no other program: no invoke or invoke_signed by any name, no CpiContext, no cpi module.
Anchor's init is fine. A hook acts only through its answers to the token program.
- Moves no SOL and closes or resizes no account (read a balance with .lamports() only).
- No unsafe, no asm!, no macro_rules!, macro or cfg_attr, no extern, no_mangle or link; nothing
read from the build machine (include_*!, env!, option_env!, #[path]); no std::fs, net, process,
os, env or thread.
- Exactly one declare_id!: the builder writes the id Bordrless reserves. On my machine, use the
address of target/deploy/my_hook-keypair.json (solana address -k <file>). One #[program] module.
- The standard prepare: an Anchor instruction named prepare, no arguments, accounts
payer (signer, writable)
mint (read-only; it may not exist yet)
state = PDA(["state", mint], hook) (writable; seeds = [b"state", mint.key().as_ref()])
registry = PDA(["bordrless-hook-accounts", mint], hook) (writable)
system program
It creates the hook's state for the mint and writes its registry (write_registry in the
crate). The launch sends it for each new mint itself; anyone may send it, once per mint.
- The registry, written by prepare and never again, lists at most 4 accounts: the hook's own
PDAs, the mint's holdings (token program) and its launch (launchpad); as fixed keys only the
system program, a sysvar or the token program. None may depend on who sends or receives (no
SourceOwner or DestinationOwner seed): a launch passes one slice of accounts for every transfer.
THE READING, by AI (Bordrless's one AI pass over the code): it writes what the site shows a
launcher before they pick the hook, and judges it. It reports a title, what the hook does in one
sentence, the most it takes from one trade (bps), a description, notes to watch, and its RULES as
exact rows, one per rate or tier, lowest first, the 0% tier included, each a label and a
statement: "Under 5M tokens: 0% hook tax", "5M-10M tokens: 3% of the tokens on buys and sells, to
the pot", "Transfers: free", "The launcher's own trades: free". A rate read from an account the
code doesn't bound shows as no fixed rate. So: write every rate, threshold and period as a named
constant (bps, base units, seconds), one tier per constant, compared in one place; make each
branch say its side (a buy, a sell, a send); put the hook data layout in a comment, with offsets.
The largest cut the trading test measured is given to the reading, which looks for the path that
takes it. It also judges the code: a critical or high finding is a fail, a medium one a warning;
the verdict and findings are shown on its page and never hold it. What passes the rules, the
build and the trading test is approved on the spot.
It reads the code with comments and strings blanked out (and those apart, as data), and calls
these deception (high):
- any way for one party to change how the callbacks behave after launch: an instruction besides
prepare and the callbacks that writes state, behaviour keyed to a wallet or an account someone
controls, reading the instructions sysvar;
- a hard-coded address the hook's plain purpose doesn't explain;
- any comment or string addressed to a reviewer, an AI or an auditor.
It also checks the arithmetic (checked math; never panic on what a trader controls), callbacks
anyone could make fail for everyone, and accounts sized far beyond what they store.
THE TRADING TEST, on Bordrless's builder: test wallets buy, sell and send over a simulated year.
It fails a hook that refuses an ordinary buy, sell or send, takes more than 15% of a transfer,
or whose flags and code disagree.
A SOL CUT, optional: a token hook sees only tokens. To take SOL on trades too, implement the
launchpad's callback quote_cut (bordrless-programs docs/quote-cut.md): accounts [the launchpad's
signer PDA(["quote-cut", hook], launchpad), launch, pool, base mint, quote mint, the trader, the
trader's holding of the token, the hook's state (writable)]; the argument the trade's PoolHookArgs
(a buy before the swap, amount_in the SOL in; a sell after it, amount_out the SOL out); the answer
a u16 of basis points as the return value (-> Result<u16>). The launchpad takes min(answer, cap)
of that SOL, the hook's own fee on top of the launch's, paid with the creator fee (on a pair it
lands whole in the pot). Check the signer, answer every call it makes without failing, only read.
Then ship hook.json beside src/ with the caps:
{ "version": 1, "quoteCut": { "maxBuyBps": 800, "maxSellBps": 0 } }
maxBuyBps 1 to 1000, maxSellBps 0 to 1000 (0: never asked on sells). A quote_cut without hook.json
is refused, and so is a hook.json without quote_cut. The trading test runs the cut at the caps and
checks every cut is min(answer, cap); the reading reads the caps beside the code, and its row
says the rate and where it goes (to the launcher; on a pair, to the pot).
TEST before submitting, on my machine. Build with cargo build-sbf --tools-version v1.57 --arch v3
(the Solana CLI, Agave 4.3). Then test prepare, a config naming the hook, a launch, buys, sells,
sends, every cut and every refusal, in LiteSVM or solana-test-validator, against the live
programs copied from mainnet (solana program dump -u mainnet-beta <PROGRAM_ID> <file>.so) and the
accounts they read, cloned from mainnet. Load the hook upgradeable only by Bordrless's key, as on
mainnet: CS1NRyXNCPxEUP4CRoa26cHQSeSJCxXh5SPijwFhDW6W. The launch program refuses a config whose
hook anyone else can upgrade (HookUpgradeable). The trading test itself is studio-sim in the
monorepo (programs/tests; tools/studio-builder/sim/run.mjs shows its flags): with the repo checked
out, cargo build --release -p bordrless-program-tests --bin studio-sim runs it on my binary too.
DO NOT deploy it to mainnet: Bordrless deploys it.
SUBMIT: https://bordrless.app/workshop/submit
I sign in with the wallet that will earn from it (it signs a message; nothing moves), choose
Hook, add the files under src/ (and hook.json beside them for a SOL cut), a name and a few
words, and choose my share of the creator fee of every launch someone else makes with it: 0% to
50%, in 5% steps. I pay the submission fee on its page (a fixed amount of SOL, shown first), and the
checks above run on their own. What passes the rules, the build and the trading test is approved
by itself; the reading is shown with it. A failed check says why: I fix the files and send the
fix from its Workshop page, and the checks run again. A wallet may submit 6 times a day.
Once it is approved, I pay the quoted deploy cost (the program's rent, network fees and
Bordrless's fee) and Bordrless deploys it with its own upgrade key. I never hold that key, so
nobody can change a launched token's hook behind its holders' backs; a new version is a new
submission. Then I make its launch config from its Workshop page, with a creator fee of
a whole quarter of a percent, 0.25% to 5%. Or I make it with the SDK (buildCreateListedConfig on my
hook): once a launch uses it, the Workshop adopts it. Launchers pick it under Workshop config on the
launch page, and I earn the share I chose (0% to 50%) of the creator fee of every launch
someone else makes with it, fixed on chain.
KNOW: a launch with a custom hook has no kit rules (holder rewards, max wallet, the locks): it is
the mint's only hook, so build what it needs into it. Bordrless takes 25% of what a launch's
rules collect on each swap, the hook's cuts included. The checks are a reading by AI and a test,
not an audit: never call the hook audited, safe or guaranteed.
READ:
https://bordrless.app/sdk/build this walkthrough
https://bordrless.app/sdk/hooks the hook protocol, in full
https://bordrless.app/docs/protocol2. Test it on your machine#
Your agent writes the code and its tests. Run them against the live programs copied from mainnet before you submit. Don’t deploy it: Bordrless does, once it is approved.
# Build it, with the Solana CLI (Agave 4.3) and the Cargo.toml above
cargo build-sbf --tools-version v1.57 --arch v3
# Its id on your machine, for declare_id! (Bordrless's builder writes the real one)
solana address -k target/deploy/my_hook-keypair.json
# The live programs your tests load, copied from mainnet
solana program dump -u mainnet-beta 2XoEWp8cF3kRXg74eVwPAyTFhVCAztn3V88komxAvr22 token.so
solana program dump -u mainnet-beta GyzKSnnEu2uN5bBRecE4XYY2enbfR2D2MtxnbJPGy7hk dex.so
solana program dump -u mainnet-beta 1jcBymHxBjniZDhNPy51Vgm5Nz7pLUdxa9UBHc4TavC launchpad.so
# A local validator with them, and your hook upgradeable only by Bordrless's key, as it
# will be on mainnet (add -u mainnet-beta --clone <address> for each account they read)
solana-test-validator --reset \
--bpf-program 2XoEWp8cF3kRXg74eVwPAyTFhVCAztn3V88komxAvr22 token.so \
--bpf-program GyzKSnnEu2uN5bBRecE4XYY2enbfR2D2MtxnbJPGy7hk dex.so \
--bpf-program 1jcBymHxBjniZDhNPy51Vgm5Nz7pLUdxa9UBHc4TavC launchpad.so \
--upgradeable-program <YOUR_PROGRAM_ID> target/deploy/my_hook.so \
CS1NRyXNCPxEUP4CRoa26cHQSeSJCxXh5SPijwFhDW6W
# Then your tests, there or in LiteSVM: prepare, a config naming your hook, a launch,
# buys, sells and sends, every cut and every refusal
3. Submit it to the Workshop#
On the Workshop, sign in with your wallet (it signs a message), choose what it is (a hook, a companion, or a pair), add your files under src/ with keeper.json or hook.json beside them (a pair: the hook’s and the companion’s), give it a name and a few words, and choose your share of every launch someone else makes with it: a hook’s, 0% to 50% of the creator fee in 5% steps; a companion’s or a pair’s, 50% of the launcher’s part of the creator fee, or nothing. Then you pay the submission fee on its page: a fixed amount of SOL, shown before you submit, to cover the cost of checking it; not refunded. Until it is approved, only you see it, signed in. A custom hook on the trades then goes through these, on Bordrless’s machines:
- The template’s rules. A scan of the code for everything the rules above forbid.
- The build. On Bordrless’s builder, in a sandbox with no network: your files in the template.
- The trading test. Test wallets buy, sell and send over a simulated year. A hook that refuses an ordinary trade, or takes more than 15% of one, fails.
- A reading by AI. Its rules as exact rows (“5M–10M tokens: 3% of the tokens on buys and sells, to the pot”), the most it takes, what to watch for, and what it finds in the code: anything malicious or broken is a finding, with a verdict.
- Approval. On the spot, once the rules, the build and the trading test pass. The reading is shown with it, its findings included; it never holds the approval.
Its page in the Workshop shows each check as it runs. One that fails says why: fix your files and send the fix from that page, and the checks run again. A wallet may submit 6 times a day. A companion goes through the same checks, without the trading test. A pair goes through both sets, with one reading, and is approved as one, bound to both builds.
4. Approval and deploy#
Once it is approved, you pay what deploying it costs. Its page quotes the amount, part by part, before your wallet signs:
- Rent
- What Solana keeps in the program’s account for as long as it exists, with room for a fifth more code. Most of the cost.
- Network fees
- The transactions that write the program and deploy it.
- Bordrless’s fee
- For the deploy. It goes to Bordrless’s revenue wallet.
A hook of about 150 kB comes to about 1 SOL, nearly all of it rent. A pair is two programs: one quote with both parts, one payment, both deployed together.
Then Bordrless deploys it as a program of its own, with Bordrless’s upgrade key. You never hold that key: a hook runs on every trade of every token launched with it, so whoever held it could change those tokens’ rules after people bought. This way nobody can change a launched token’s hook behind its holders’ backs. A new version of your hook is a new submission.
5. Its launch config and your earnings#
Once it is deployed, make its launch config from its page in the Workshop: a config on your hook with no kit rules, and a creator fee you choose. Or make it with the SDK (buildCreateListedConfig on your hook) and launch with its key under Custom config: once a launch has used it, the Workshop adopts it. Either way it is listed in the Workshop, and launchers pick it under Workshop config on the launch page. A pair’s config also requires its companion: a launch with it gets both or neither.
- Creator fee
- Any whole quarter of a percent of every trade, 0.25% to 5% (a pair’s: the creator fee and the companion fee together). You choose it once, and the config keeps it; a launcher can’t change it.
- A pair’s split
- The pair’s config fixes how its fee splits between the launcher’s creator fee and the pot’s companion fee: half each unless you set the split on its Workshop page, or its keeper.json fixes it (launcherShareBps, which wins). A launcher can’t adjust it.
- You earn
- 0% to 50% of that fee, in 5% steps, on every launch someone else makes with your hook’s config, fixed on chain: you choose at the submission, and again at the config step. You claim it as SOL from your portfolio.
- A companion or a pair
- 50% of the launcher’s part of the creator fee each claim takes (or nothing), paid by the companion program out of that part: never from the pot, buybacks, holders or the hook’s SOL cut. Launchers pick a companion under Companion fee on the launch page; a pair’s comes with its config.
What Bordrless checks#
- A reading by AI and a test, not an audit. They catch a lot, not everything. Read a hook’s page and its code before you launch with it.
- What holds whatever the code says. The token program never lets a hook take more than the amount or move anyone’s tokens itself, and only Bordrless’s key can upgrade a Workshop hook.
- A companion keeps the companion program’s limits whatever its code does: the companion program checks every step and refuses one that spends more than the pot, touches the dev’s tokens or takes the companion address’s rent.
- What the site shows of your program. A Workshop hook or companion comes with Bordrless’s reading of it, in Bordrless’s words, on the launch page and the token page: its rules as exact rows, the most it takes, what to watch, and what the reading found. Write the rates, thresholds and periods as fixed constants and clear tiers, so the rows state them exactly; the trading test’s largest cut is held against them. One you deployed yourself shows as a custom hook written by its creator, with who can upgrade it, and no reading, unless you submit its source with its address for the reading.
More on each: write a hook, companions, with the SDK and how a companion works.