Design decisions
Each major choice in Grail, the reason for it and what it costs. Some of these replaced earlier designs that turned out to be wrong.
A Uniswap pool from the first block
Grail first ran a bonding curve in its own contract and moved tokens to Uniswap on graduation. While a token was on the curve, terminals and aggregators could not see it, so it could only be bought on Grail. We retired the curve before mainnet.
Now the whole supply goes into one single-sided Uniswap v3 position at launch. Its price follows the same curve shape as a virtual-reserve launchpad, with no migration, and any terminal can trade the token at once. The cost: anyone can open another fee tier for a token, and trades routed there pay Grail nothing. All launch liquidity stays in the 1% pool, so we expect most volume to stay there too.
Uniswap v3, not v4
On mainnet, anyone can apply Uniswap's protocol fee of one sixth to a 1% pool, so 0.833% of volume reaches the position instead of 1%. A v4 hook could charge the full 1%, but it means a rewrite of the contracts and of the private trade path. We stayed on v3 and publish the lower numbers.
No token tax
A transfer tax would be the simple way to earn more per trade, but Railgun rejects fee-on-transfer tokens, and a token that cannot be shielded cannot be traded privately. Grail tokens are plain ERC-20s with no owner, no mint and no tax. Creator income comes only from the pool fee.
A private balance, like a terminal wallet
Railgun deposits go through a standby period of about an hour. Instead of hiding that, Grail treats the private balance as a first-class account, the way trading terminals use deposit wallets: top it up once, wait once, then trade without further waiting. The standby applies to new money entering Railgun, not to each trade. See Deposits and the standby.
A broadcaster, so the wallet never appears
If the user's wallet sends a private transaction, its address is the transaction's sender, and the privacy is gone. We saw this in our first test: the trade looked private on our site, and the explorer showed the test wallet as the sender. Grail runs its own broadcaster, which sends the transaction and takes its fee from the private balance. The cost: it is one operator, so it sees request IP addresses and is a smaller crowd than a network of broadcasters.
A random recovery phrase, not a wallet signature
An early prototype derived the private wallet from a signature, which was convenient and also wrong, because a signature can be phished. It now uses a random phrase the way Railgun's wallet guide does. Private wallets tells the full story. The cost: the user has one more thing to write down.
A downloaded tree, not a full sync
A new wallet has to read Railgun's public tree. On mainnet, syncing it from scratch took 25 minutes and 2.4 GB of memory, far too much for a browser tab. Grail's server keeps a synced copy and the browser downloads it in small resumable parts. The first sync has the details. The cost: users depend on Grail's server for the first open, and the browser still stores about 600 MB.
Public launches, private trading
Creating a token is public by design, from a normal wallet, so buyers can see who launched what. A creator who wants a private position can add a private buy, which lands right after the launch.
Rules fixed at deployment
The launch fee, start price, launch guard and fee split are set when the contract is deployed and can never change. A token's fee recipient is set once at launch and can never change. Liquidity is locked in a contract with no withdraw path. The contracts are not upgradeable, so a new version would be a new deployment. These limits protect creators and holders from us as well as from anyone else.
Grail is an independent project built on Railgun's public contracts and SDK. Railgun contributors do not run, review or endorse Grail, and they did not write this documentation. Their own documentation is at docs.railgun.org.