What this is
DOGMA CAPITAL is a trading desk for Robinhood Chain (chain 4663). It does three things, and all three happen on chain:
- Aggregates liquidity. Every venue and every fee tier is swept into one consolidated book.
- Routes smartly. An order is split across venues when a split fills it better, and settled in one transaction.
- Renders a terminal. A dense workspace over that book, with the provenance of every number stated next to it.
There is no private matching engine, no off-chain quote server and no internal order book. Everything the desk knows about price comes from pool state in the current block, and everything it does about it happens through contracts whose addresses are published.
Liquidity aggregation
The same instrument trades in a dozen pools at once, each with its own depth and its own fee. Asking one of them for a price is not aggregation; asking all of them, for the size you actually intend to trade, is.
DogmaBook.book(tokenIn, tokenOut, amountIn) walks every venue in
DogmaVenueRegistry and every fee tier that venue declares, prices the full
size against each, and returns one ladder sorted best first.
How each level is priced
| Model | Method | Exactness |
|---|---|---|
| Constant product | Closed form from the reserves, with the venue's own fee applied to the input. | Exact at any size. The arithmetic is the pool's own invariant. |
| Concentrated liquidity | The pool is asked. DogmaQuoter starts the real swap and reverts inside the pool's own callback before any token moves, then reads the amounts the pool had already computed. |
Exact, including tick crossings and fees, because the pool did the maths. |
Because the concentrated path deliberately reverts, those functions cannot be marked
view. They are called with eth_call, which is how the app calls
them and how you should too.
UntilDogmaBookandDogmaQuoterare deployed, the desk still reads the same pool state live for the current block, but the concentrated legs are approximated with constant liquidity. This is accurate for ordinary sizes and optimistic for very large ones. Every quote carries amodefield, and the terminal prints it next to the price: Exact or Indicative. A price whose derivation is invisible is a price nobody can check.
Smart order routing
A split beats the single best venue for one reason: the margin moves. Once part of an order has been pushed through a pool, that pool's price has changed, and the next part is usually worth more somewhere else.
So the solver works at the margin rather than on averages:
- Price the whole size against every venue. Keep the deepest few: spreading thinner than four legs loses more to gas than it wins on price.
- Cut the order into slices (twelve by default).
- For each slice, ask every candidate what it would pay for its current allocation plus this slice, and give the slice to whichever pays the most extra.
- Stop when nothing can absorb another slice.
- Compare the result against the single best venue. If the split does not actually beat it, discard the split.
That last step matters. A split that ties with the best single venue still costs an extra pool swap in gas, so returning it would be charging the user for nothing. The desk falls back instead.
The improvement grows with size. On a small order one pool absorbs everything without moving, and the solver correctly declines to split.
The guarantee
DogmaRouter makes exactly one promise and enforces it in code: the recipient
receives at least minAmountOut, or the whole transaction reverts.
amountOut = IERC20(tokenOut).balanceOf(recipient) - balanceBefore;
if (amountOut < minAmountOut) revert InsufficientOutput();
Three consequences follow, and they are the whole point of the design:
- A split cannot half-fill. Every leg settles inside the same transaction. Either the total beat your floor, or the chain is exactly as it was before you signed.
- A soft leg is not a failure. Per-leg minimums are deliberately zero. The check is at the order level, so one venue coming in below expectation is fine as long as the order as a whole did not.
- A revert costs gas and nothing else. Your input is never transferred.
The fee is charged on the input, before any venue sees the order. That is
what makes minAmountOut checkable: the fee is already inside the amount the
route was priced on, so the quote and the floor are directly comparable numbers.
Every order is re-solved on the server at the moment you press execute. A quote shown thirty seconds ago was priced on a block that has since been replaced, and signing a minimum derived from it is how an order reverts for a reason nobody can see afterwards.
The terminal
Three columns, because that is what the eye actually does: pick an instrument on the left, read the price in the middle, act on the right.
| Key | Action |
|---|---|
| / | Focus the instrument filter |
| ↑ ↓ | Move through the instrument list |
| B | Open the ticket to buy the selected instrument |
| S | Open the ticket to sell it |
| W | Add or remove it from the watchlist |
| R | Refresh every panel now |
The round trip column is the honest spread: sell one unit, buy it straight back, and measure the shortfall. It is fee and slippage together, which is what actually comes out of a taker's pocket, and no single mid-price can express it.
The depth curve prices the same pair at one, two, five, ten, twenty-five, fifty and a hundred times a base size. On a thin chain that shape decides whether a position can be exited at all, which is a more useful question than what the top of book says.
Contracts
Eight contracts, deployed in a fixed order from one deployer at nonce 0. Because a CREATE address is a pure function of the deployer and its nonce, every address below was determined before any transaction existed.
| Nonce | Contract | Address | What it does |
|---|---|---|---|
| 0 | DogmaVenueRegistry | 0xe81a…d9F5 | The on-chain list of liquidity venues the aggregator reads. Deployed first because the Quoter, the Book and the Router all take it as a constructor argument. |
| 1 | DogmaAssetRegistry | 0x47CC…F26d | Every instrument the terminal will price, with its class, decimals and quote asset. The front end boots off this contract, not off a server-side file. |
| 2 | DogmaQuoter | 0xefbB…FFd2 | Prices a size against one venue. V2 in closed form; V3 by starting the real pool swap and reverting inside the pool callback before anything settles. |
| 3 | DogmaBook | 0x410F…a53d | Consolidates every venue into one sorted book and solves the split the router executes. Read-only in effect - it changes no state anywhere. |
| 4 | DogmaTreasury | 0x2451…7702 | Every fee lands here and is split by published shares. Sweeping is permissionless; the destinations are fixed on the books. |
| 5 | DogmaRouter | 0x43Be…1773 | Settles a split route in one transaction and enforces the signed minimum output, or reverts. Fee is capped at 1.00% in the deployed bytecode. |
| 6 | DogmaToken | 0x3a27…3FC4 | Fixed-supply ERC-20 with EIP-2612 permit. No mint, no tax, no pause. Staked for a desk tier. |
| 7 | DogmaStaking | 0xC487…5B3A | Stake DGMA to hold a tier. Rewards are funded, never minted, so the runway is visible on chain before anyone stakes. |
The deployer has two rails and both stop the run rather than guess: it refuses to deploy unless its nonce is 0, and it aborts on the first contract whose deployed address does not land on the reserved one.
Venues
| ID | Venue | Model | Fee |
|---|---|---|---|
| 1 | Concentrated V3 | Concentrated liquidity | 0.05%, 0.30%, 1.00% |
| 2 | Constant Product V2 | Constant product | 0.30% flat |
The router can only reach a venue listed in DogmaVenueRegistry. Listing one is
an owner action; disabling one is delegated to the keeper. A compromised keeper can degrade
routing but can never widen it.
Fees and tiers
The router fee is 0.25% on the input. The cap is 1.00% and it is a constant in the deployed bytecode, checked on every write: no owner key can raise it past that.
Fees land in DogmaTreasury and are split by published shares that must total
exactly 100%. Sweeping is permissionless: anyone may trigger the distribution, and the
money can still only travel to beneficiaries already on the books.
Staking DOGMA in DogmaStaking assigns a desk tier, and a tier rebates part of
the router fee. The rebate applies to the DOGMA CAPITAL fee only, never to a venue's own
pool fee: the desk does not receive that and cannot discount it.
HTTP API
Read endpoints are open. They serve the same numbers anyone can compute from the chain, and a desk that hid them while claiming to be verifiable would not be verifiable. Anything that writes, or reads one wallet's private state, needs a session.
Every response is the same envelope, so success and failure are distinguished by a field rather than guessed from the shape:
{ "ok": true, "data": { … }, "served_at": "2026-01-01T00:00:00Z", "timezone": "UTC" }
{ "ok": false, "error": { "code": "no_route", "message": "…" }, "served_at": "…" }
Public endpoints
| Endpoint | Returns |
|---|---|
| GET /api/markets.php | The instrument universe with price, change, depth and venue count. |
| GET /api/instrument.php | One instrument in full: listing, stats, live book, pools, depth curve. |
| GET /api/book.php | The consolidated ladder for a pair at a size. |
| GET /api/quote.php | The solved split, the minimum output, and the router calldata. |
| GET /api/depth.php | Slippage against order size. |
| GET /api/venues.php | The routing surface and how each venue is performing. |
| GET /api/candles.php | OHLCV, cut on UTC boundaries. |
| GET /api/tape.php | The consolidated tape, with the venue behind each print. |
| GET /api/contracts.php | The deployment record, code-checked against the chain. |
| GET /api/stats.php | Desk-wide statistics. |
| GET /api/health.php | Chain reachability and desk state. |
A worked quote
amount is in raw units, never a human decimal. An endpoint that
accepted 1.5 would have to guess the decimals, and guessing decimals is how an
order ends up a thousand times larger than intended.
curl "https://dogma.capital/api/quote.php\
?token_in=0x5fc5360d0400a0fd4f2af552add042d716f1d168\
&token_out=0xd0601ce157db5bdc3162bbac2a2c8af5320d9eec\
&amount=100000000\
&slippage_bps=50"
That is 100 units of a 6-decimal asset. The response carries
expected_out, single_venue_out, improvement_bps,
min_out, the legs to execute and, once the router is deployed,
the exact calldata to send.
Rate limits and keys
120 requests a minute per IP without a key. Create
one in Settings for a higher ceiling counted against your
wallet, and send it as X-Dogma-Key. Only a hash is stored, so the key is shown
once and cannot be recovered afterwards by you or by the desk.
Time and UTC
Everything on this desk is UTC, and it is pinned in three independent places:
- The PHP runtime:
date_default_timezone_set('UTC')in the bootstrap. - The MySQL session:
SET SESSION time_zone = '+00:00'on every connect, soCURRENT_TIMESTAMPcannot follow the server's local zone. - The schema: every timestamp column is written and read as UTC, and nothing is converted on the way in or out.
A blotter that mixes zones cannot be reconciled: two rows an hour apart might be two hours apart, or the same instant recorded twice, and the rows themselves cannot tell you which. You may switch your own display to local time in Settings; the stored value never changes, the API always answers in UTC, and the masthead clock stays UTC because it is the desk's clock rather than yours.
Security model
Authentication
A wallet signature is the only credential. There is no password anywhere in this
application, nothing to leak from the database, and nothing to reset. The server issues a
single-use nonce with a short expiry, the wallet signs the message with
personal_sign, and the server recovers the signer with its own secp256k1
implementation and compares it to the claimed address.
The EIP-191 prefix inside the signed bytes is what makes that signature impossible to replay as a transaction. Signing in authorises nothing, moves nothing and costs no gas.
Keys
One key per role, deliberately. A compromised fee key cannot move treasury funds. The keeper, the only key that is ever hot, holds no revenue and is authorised for upkeep calls only. It can suspend a venue or an instrument, and it cannot re-enable either.
Private keys live in tables/master_table_dogma_capital.json, outside the web
root. Nothing under public/ reads that file, no key is ever written to the
database, and no endpoint can return one.
What the contracts cannot do
- The router cannot charge more than 1.00%: the cap is in the bytecode.
- The router cannot touch an unlisted venue.
- The router holds nothing between transactions; anything stuck in it can only be swept to the fee sink.
- The Book and the Quoter hold no funds, have no owner, and cannot move a token.
- Staked principal is not the owner's to touch: only the surplus above what stakers and the reward pool are owed.
- DOGMA has no mint function, no rebase, no transfer tax and no pause.
Running it yourself
Requires XAMPP (Apache, PHP 7.2+, MySQL/MariaDB) and Node 18+ for the contract tooling.
# 1. Database
mysql -u root -e "CREATE DATABASE dogma_capital CHARACTER SET utf8mb4"
mysql -u root dogma_capital < sql/schema.sql
mysql -u root dogma_capital < sql/seed.sql
# 2. Configuration
copy config\app.sample.php config\app.php # edit the db block
# 3. Contract tooling
cd contracts
npm install
npm run keys # generates tables/master_table_dogma_capital.json
node scripts/sync.js # publishes addresses to config/contracts.json
npm run compile
# 4. Fill the universe from the live chain
php tools/discover.php # finds what actually trades here
php tools/indexer.php # prices it
# 5. Deploy (needs gas on the deployer)
cd contracts
npm run deploy -- --dry-run
npm run deploy
cd ..
php tools/sync_contracts.php
Schedule php tools/indexer.php once a minute and
php tools/settle.php once a minute. The app degrades gracefully without them.
The terminal still reads the chain live, but prices, candles and the blotter stay stale.
Full setup notes, the schema reference and the contract reference are in the
docs/ directory of the repository.