01The costume
Why every bridge fails the same way
Every bridge failure in history is the same sentence: the custody was real, the claim was not. You hand an asset to a contract on one chain, it mints a receipt on another, and the receipt is worth exactly what the guard of the original is worth.
The cryptography is almost never what breaks. What breaks is the reporter — some address, committee, multisig or relayer trusted to say what the other side looks like. Wrapping and custody are not features of bridging; they are the attack surface.
The inversion
Unbridged never asks you to move anything. You declare yourself present, and the protocol reads your balance where it already is. Nothing is wrapped, nothing is locked, and no contract in this system can hold, move, freeze or mint a single UBR.
02Attestation vs verification
The whole argument, in one control
Both models below answer the same question. One is told the answer by a reporter; the other checks. Corrupt the reporter and watch which one notices.
Bridge
Attested
Unbridged
Verified
isPresent() reads it100,000There is no honest-reporter setting on the right-hand side, because there is no reporter. That is not a stronger assumption — it is one assumption fewer.
03The proof system
Stated in the vocabulary it belongs to
Zero-knowledge storage proofs exist to delete the reporter: they let a verifier check a state slot it cannot read, instead of being told about it. Unbridged is that thesis carried through the whole system — verification everywhere, attestation nowhere. Reduced to its floor, Presence is a proof system, and it is worth writing out as one:
FLOOR of UBR.Presence.isPresent(address) — two SLOADs.
On the chain where the state lives you can simply read it, so the proof collapses into the check
itself. The prover is the chain. Same guarantee, same trust model, none of the
circuit — and one SLOAD instead of a pairing.
Soundness
No false statement can be accepted. isPresent() cannot be made to return true for
an address below the floor, by anyone, at any price. It re-reads the balance at the instant it
is asked: no cache, no snapshot, no admin override. There is no stale-proof window
because there is no stored proof.
Completeness
No true statement can be censored. Anyone above the floor may call declare() —
permissionless and unpriced — and no address can be removed, blocked or expired by anyone,
including the deployer. No merkle root to be included in, no signature to obtain from a server.
04Presence
The register — declared by the holder, never assigned
declare() is callable once per address, ever. It costs gas and
nothing else: no approval, no transfer, no stake, no deposit. The register writes down the
block you declared at and increments two counters.
function declare() external {
if (declaredAt[msg.sender] != 0) revert AlreadyDeclared();
uint256 held = token.balanceOf(msg.sender);
if (held < FLOOR) revert BelowFloor(held, FLOOR);
declaredAt[msg.sender] = uint64(block.timestamp);
unchecked { reach += 1; }
bool sovereign = msg.sender.code.length == 0;
if (sovereign) { unchecked { sovereignReach += 1; } }
}
sovereign records whether the declaring account carried no code at that moment —
a plain key, not a contract. It is published as a statistic and deliberately settles no value.
There is no undeclare
Not an oversight. There is nothing to give back, and nothing to revoke — the verifier already stops answering true the moment the balance drops. A function to undo it would be decoration.
05The live witness
A declaration is about the past; presence is about now
Because the witness is read fresh on every call, a declaration that is no longer backed stops verifying the instant the tokens leave — with no keeper, no expiry job and nothing to prune. Drag the balance below the floor and watch the verifier answer.
The declaration never changes — it is intact in every state above. Sell back above the floor and you are present again, on the same declaration. State cannot lie about itself.
Why sybils prove nothing
The economics are per-address, not global. A valid proof lowers the fee on your swaps
and nobody else’s, so splitting a balance across a hundred wallets buys a hundred proofs of a
hundred smaller positions and costs a hundred floors to carry. It gains nothing, and
reach settles no value, so inflating it purchases a larger number on a picture and
not one wei.
06The hook
Verification at the point of execution
What proofs buy is the right to act on state you did not write. A Uniswap v4 hook is where that becomes useful: it runs inside the swap, so a proof checked there decides execution itself rather than being posted somewhere afterwards and hoped about.
function beforeSwap(...) external view returns (bytes4, BeforeSwapDelta, uint24) {
if (!_isOurPool(key)) return (selector, ZERO_DELTA, 0);
uint24 fee = presence.isPresent(tx.origin) ? PRESENT_FEE : BASE_FEE;
return (selector, ZERO_DELTA, fee | OVERRIDE_FEE_FLAG);
}
Both figures are ordinary Uniswap LP fees paid to liquidity providers. The hook takes no share and holds no balance, and has no withdrawal function because it has nothing to withdraw. Both fees are immutable and hashed into the hook’s mined address — the fee you read today is the fee forever.
Dynamic-fee pool — required
The pool must be initialised with key.fee == 0x800000 (8388608) and
tickSpacing == 200. beforeInitialize rejects anything else, so the
pool cannot be created with the wrong parameters — by you or by anyone.
07The commitment chain
Sealed by anyone, attested by nobody
A proof system needs something to prove about. Ledger keeps a growing
chain of sealed readings: one immutable entry per four-hour epoch, each a commitment to what the
register held, permanent the moment it is written.
seal() takes zero arguments
It accepts no claims, no submitted proofs and no signatures. It reads Presence and the token directly, at the block it is called, and writes down what it found. There is nothing to forge and nothing to dispute. Two callers in the same epoch get the same answer, and the second reverts.
struct Entry {
uint64 sealedAt; // when it was written
uint32 reach; // declarations ever made
uint32 sovereign; // of those, from accounts with no code
uint128 burned; // UBR destroyed, ever, at that moment
}
Sealing is permissionless and unrewarded on purpose. There is nothing to win by sealing early, late or often, so there is nothing to game — an epoch nobody seals simply has no entry, and the gap is visible in the chain forever.
08Emissaries
A commitment made portable
An emissary is the oldest answer to the cross-chain problem, and the one every proof system is trying to replace: you cannot send the state, so you send someone who saw it. This is that, made literal — and made harmless.
claim() mints an ERC-721 that freezes the latest sealed entry and never
changes it. It carries no authority: it cannot move value, settle anything, or
be presented anywhere to unlock a balance. Its art is drawn fully on chain — a bright origin
node with sight lines out to satellites, and the spokes carry nothing, because they are sight
lines and not bridges.
Why forging one gains nothing
A bridge receipt is a claim you are expected to honour. An emissary is a copy of something already public and already immutable — anyone can check it against the Ledger without asking the holder anything at all.
09Parameters
Every number, and whether it can move
| Parameter | Value | Mutable |
|---|---|---|
| Total supply | 1,000,000,000 UBR | No — no mint exists |
| Presence floor | 100,000 UBR (0.01%) | No — immutable |
| Base fee | 10000 pips — 1.00% | No — mined into the address |
| Present fee | 4000 pips — 0.40% | No — mined into the address |
| Epoch | 4 hours | No — immutable |
| Pool fee | 8388608 (dynamic flag) | Fixed at initialise |
| Tick spacing | 200 | Fixed at initialise |
| Hook flags | 0x2080 | No — it is the address |
Contracts
| Contract | Size | Role |
|---|---|---|
UnbridgedToken | 3,005 B | UBR. The witness. No tax, no mint, no owner after launch |
Presence | 1,876 B | The verifier |
UnbridgedHook | 3,900 B | Verification inside the swap |
Ledger | 2,832 B | The commitment chain |
Emissary | 5,287 B | ERC-721 carrying a sealed commitment |
EmissaryRenderer | 3,472 B | On-chain constellation |
10Contract API
Everything an interface needs
Presence
declare() // once per address, ever
isPresent(address) → bool // the verifier; live, never cached
statusOf(address)
→ (declared, present, since, held, floor)
stats() → (reach, sovereign, floor)
declaredAt(address) → uint64
FLOOR() → uint256
UnbridgedHook
quoteFee(address) → (uint24 fee, bool present)
BASE_FEE() → uint24 // 10000 = 1.00%
PRESENT_FEE() → uint24 // 4000 = 0.40%
HARD_CEIL() → uint24 // 100000, a construction bound
Ledger
seal() // no arguments, permissionless, unrewarded
entries(uint64) → Entry
latestEpoch() → uint64
sealedCount() → uint64
EPOCH() → uint64 // 14400 seconds
GENESIS() → uint64
Emissary · Token
claim() → uint256 // mint an emissary of the latest sealed epoch
tokenURI(uint256) → string // on-chain JSON + SVG
burn(uint256) // destroy your own UBR
openTrading() // once; deletes the launcher role
11Reverts
What refuses, and why
| Error | Raised by | Meaning |
|---|---|---|
AlreadyDeclared() | Presence | One declaration per address, forever |
BelowFloor(held, floor) | Presence | You cannot declare what you do not hold |
PoolNotDynamicFee(exp, got) | Hook | Pool not initialised with 0x800000 |
WrongTickSpacing(exp, got) | Hook | Spacing is not 200 |
NotOurPool() | Hook | Wrong currency pair |
AlreadySealed(epoch) | Ledger | That epoch is already committed |
12Verify it yourself
Do not take any of the above on faith
Everything on this page is a claim about state you can read. The point of the protocol is that you never have to believe a reporter — including this website.
# am I present, right now?
cast call $PRESENCE "isPresent(address)(bool)" $YOU
# everything about one address, in one call
cast call $PRESENCE "statusOf(address)(bool,bool,uint64,uint256,uint256)" $YOU
# what would I pay on the next swap?
cast call $HOOK "quoteFee(address)(uint24,bool)" $YOU
# the fees are immutable — read them, then read them again in a year
cast call $HOOK "BASE_FEE()(uint24)"
cast call $HOOK "PRESENT_FEE()(uint24)"
# the commitment chain
cast call $LEDGER "latestEpoch()(uint64)"
cast call $LEDGER "entries(uint64)(uint64,uint32,uint32,uint128)" $EPOCH
The hook’s permissions are not a claim either — they are its address. The low 14 bits of
0x…2080 are beforeInitialize | beforeSwap, which is why the
address had to be mined and why it cannot silently gain a permission later.
13Fork results
Mainnet fork, every check passing
Buy gas measured at 102k–118k, normal for a v4 swap; the hook adds roughly
5k, which is two SLOADs and a call.
14What it cannot do
The list that matters more than the feature list
- No custody. No contract in this system ever holds UBR.
- No mint. Supply is written once in the constructor; the function does not exist.
- No owner. After
openTrading()there is no privileged address anywhere. - No fee setter. Both fees are immutable and mined into the hook’s address.
- No transfer tax. Sending UBR wallet-to-wallet costs what any ERC-20 costs.
- No pause, no blacklist, no upgrade. There is no proxy and no admin.
- Your LP is yours. The hook owns no liquidity; you add and remove it on Uniswap normally.
15Succinct proofs
Where a circuit is actually required — stated plainly
On the chain where the state lives, a storage proof collapses into the check itself: you can
read the slot, so the canonical state is the witness. That is what ships today, and it
is why verification costs one SLOAD instead of a pairing.
Extending the identical statement to a slot on another chain is exactly where a succinct proof becomes necessary — and it is the direction this design is built to take. The commitment chain exists so that a future prover has a stable, append-only sequence to prove against.
Read the source, not the roadmap
What is deployed today verifies state directly on Ethereum, with no reporter, no committee and no light-client assumption. Cross-chain proving is a stated direction, not a deployed claim — and every contract is verified, so you never have to take that distinction on trust either.
16FAQ
Short answers
Does declaring lock my tokens?
No. Nothing is deposited, transferred or escrowed. declare() costs gas and writes
a timestamp. Your tokens never leave your wallet — that is the entire point.
What happens if I sell?
The moment your balance drops below the floor you stop being present, silently and instantly. No keeper runs, nothing is revoked. Buy back above the floor and you are present again on the same declaration.
Can I declare twice, or undeclare?
Neither. declare() reverts with AlreadyDeclared() after the first
call, and there is no undeclare because there is nothing to give back.
Why can’t I create the pool on the Uniswap app?
It is a dynamic-fee pool — the fee is decided by the hook per swap, so it has no standard fee
tier. The pool must be initialised with fee = 8388608 and
tickSpacing = 200, which the app does not offer.
Who can change the fees?
Nobody. Both are immutable and hashed into the hook’s mined address. Changing either would require a different address, which would be a different hook and a different pool.
Is sealing profitable?
No, deliberately. It is permissionless and unrewarded, so there is nothing to win by sealing early, late or often — and therefore nothing to game.