Docs / Contracts
Developers
Contracts
What the written pool contracts do: functions, events, errors and fixed settings. Not deployed yet.
The contracts
| Contract | Role |
|---|---|
| OarkelPool | The pool and fee vault. No owner, no admin function, no pause, no proxy; every parameter set in the constructor |
| HonkVerifier | UltraHonk proof verifier generated from the Noir circuit; verification key fixed in code |
| PoseidonT3, PoseidonT4 | Poseidon hash libraries the pool links to |
| ZKTranscriptLib, RelationsLib | Libraries the verifier links to |
The libraries and the verifier hold no state. The contracts are written and tested but not deployed yet; their addresses will be published on the deployments page once they are live.
Pool functions
| Function | Who calls it | What it does |
|---|---|---|
shroud(asset, amount, ownerHash, encryptedNote) | Depositor (payable) | Takes ETH (asset 0) or $OARKEL (asset 1) minus the shroud fee; the pool computes the note commitment from the amount paid |
transact(proof, args, ext) | The named relayer, or anyone when no relayer is paid | Private send: two notes in, two out. Value sent to another key pays the transfer fee, enforced inside the proof |
unshroud(proof, args, ext) | The named relayer, or anyone when there is no relayer fee | Withdraws to any address, minus the flat fee and an optional relayer fee |
donate(amount) | Anyone | Adds $OARKEL to the vault backing |
sweepEthFees() | Anyone | Sends accrued ETH fees to the fee address fixed at deploy |
Read-only views: isKnownRoot, getLastRoot, spentMany, valueOfShares, previewShroudShares, state, extDataHash and zeros.
Events
NewCommitment(commitment, leafIndex, encryptedNote): one per new leaf; wallets scan these to find their notes.NewNullifier(nullifier): one per spent note.Shrouded(asset, from, amount, fee, noteValue, leafIndex): the public side of a deposit.PrivateTransfer(asset, transferFee, relayer, relayerPaid): that a private send happened, and its fees.Unshrouded(asset, recipient, relayer, amountOut, relayerPaid, protocolFee): the public side of an exit.YieldAdded,SharesBurned,Donated: $OARKEL reaching the vault.EthFeeAccrued,EthFeesSwept: ETH fees building up and leaving for the fee address.
Errors
| Error | When |
|---|---|
UnknownRoot | The proof names a root outside the last 100 |
NullifierSpent, SameNullifier | A note was already spent, or both inputs are the same note |
InvalidProof | The verifier rejected the proof |
NotRelayer, BadRelayer | A relayer-paid spend sent by someone else, or a relayer fee with no relayer |
BadRecipient, ExitTooSmall | Missing or unexpected recipient, or an exit that does not cover its fees |
BadAmount, BadAsset | A zero or mismatched amount, or an asset other than 0 and 1 |
NotInField, ValueTooLarge, NoteTooLarge | An input outside the proof field, a value above 2^120, an encrypted note over 512 bytes |
FeeOnTransferToken, ZeroShares | The token arrived short, or a shroud too small to mint a share |
TreeFull | All 2^24 leaves are used |
EthTransferFailed, NothingToSweep | An ETH payout failed, or there are no ETH fees to sweep |
BadParameter | The constructor refused a setting, such as a fee above 5% |
What is deliberately missing
No owner, no admin function, no pause, no proxy and no upgradeTo, no function that moves or freezes a note, and no fee setter. Every parameter is a constructor argument, fixed forever at deploy; the full list is on the parameters page.
Verify a deployment
Once addresses are published, anyone can check them against this code. From the repository, run npm run verify-deployment -- <address> --tx <creation tx>. It compares the deployed bytecode byte for byte with this build, checks each linked library the same way, decodes the fixed settings (verifier, token, fee address and fees) and, with --tx, checks the creation input and constructor arguments. Any mismatch fails.
The verified source, every transaction and every event can also be read on Blockscout.