Trust assumptions and admin powers
zk-pad aims for "no owner powers over balances". Some configuration powers remain. This page lists all of them.
zk-pad is deployed on BSC mainnet. Today:
- FeeVault, ZkPadFactory, QuoteRegistry and RailgunShieldAdapter are owned by a single
externally owned account (EOA),
0x529C9Ec99b8c7478886f8954236C0E7C9cb9aBaB(the deployer). It is not a multisig and there is no timelock: every owner power below takes effect in the transaction that uses it. - The same EOA is the
teamFeeRecipient(the 25% protocol share). - The guardian of FeeVault and QuoteRegistry is a separate EOA,
0x3F8B32D7b4d7C37ed9Fe21B8f5f2a57e77de94AC. - No attestors are registered and
attestorThresholdis 0, soproposeBindreverts withInsufficientAttestations: social-account escrows cannot be bound or claimed until attestors are added. Fees credited to an escrow stay in the vault, but an escrow with a fallback recipient can be swept to it by anyone once its fallback delay (at least 180 days) passes without a bind.bindDelayis 48 hours.
Every admin contract uses Ownable2Step. The plan is to move ownership to a Safe multisig
(the EOA calls transferOwnership, the Safe calls acceptOwnership on each contract) and to put
a timelock longer than the bind delay in front of it. Until that happens, you are trusting one
private key. All addresses are on the addresses page.
Protocol roles
ZkPadFactory owner
| Can | Cannot |
|---|---|
setDeprecated: stop new launches | Affect existing launches |
setHook, setLocker, setMevModule: enable/disable components for new launches | Change an existing pool's hook, locker or MEV module |
setQuoteToken: allow-list quote tokens and their tick bounds (also callable by quote-token admins) | Disable trading of existing pools |
setAdmin: grant the quote-token admin role (intended for the QuoteRegistry) | |
setTeamFeeRecipient: choose where the 25% protocol fee goes (claimTeamFees is permissionless and pays the current recipient) | Touch the beneficiary's 75% |
FeeVault owner
| Can | Cannot |
|---|---|
setAdapter: allow or remove withdrawal adapters | Move or freeze any balance |
setAttestor, setAttestorThreshold: manage the attestor set (threshold between 1 and the attestor count) | Bind an escrow without k attestor signatures and the timelock |
setGuardian | Redirect any account |
setBindDelay: 1 to 30 days | Shorten an already-pending bind |
recoverSurplus: recover tokens sent outside deposit | Take more than balanceOf(vault) − totalBalance(asset) |
setConsolidationConfig: the first call sets the QuoteRegistry, USDT and the launch factory; later calls may only replace the registry | Change USDT or the launch factory once set (they decide what is settled and who counts as a creator) |
setShieldAdapter: the adapter new shield templates are pinned to (address(0) turns template shielding off) | Redirect an already-registered template: a template is only used through the adapter it was registered under, while that adapter is still configured and allow-listed (a change can block it, never redirect it) |
setMinCreatorShield: the minimum oracle value of a creator consolidation and of a template shield (1 USDT by default) |
Risk: removing an adapter (for example the Railgun adapter) disables that exit until it is re-allowed. Direct claims cannot be disabled.
Risk: the creator path's price bound is owner configuration. Creator-triggered
consolidations are bounded by the QuoteRegistry's Chainlink feeds and route executors, and the
FeeVault owner chooses the registry. setQuote can check that a feed answers and that an
executor reports USDT as the route output, but not that the feed is a real aggregator or the
executor honest. A malicious owner working with a launch creator could therefore make that
launch's credited balances (launchCredit) swap for almost nothing. Donations, other
launches' credits, anything the owner already withdrew, and the beneficiary-signed path (bounded
by its own minOut) are out of reach. A beneficiary who does not want to rely on this can
consolidate or claim the balance itself. Monitors should watch QuoteSet,
ConsolidationConfigSet, ShieldAdapterSet and AdapterSet.
Risk: a malicious or compromised owner controls the whole bind security model. It could
remove the guardian (setGuardian(address(0))), remove honest attestors, add its own and set the
threshold to 1. It could then bind or rebind social-escrow accounts to its own key. What remains
is the public timelock (at least 1 day, 2× for rebinds), during which the change is visible
and the current owner of an already-bound account can cancelBind. An unbound escrow has no owner
who can cancel. This is why the owner should be a multisig behind a timelock longer than the bind
delay. Today it is a single EOA with no timelock (see the warning above), so this risk rests
on the safety of one private key. Stealth-key accounts are not affected: binds only apply to
social escrows.
Guardian
Currently the EOA 0x3F8B32D7b4d7C37ed9Fe21B8f5f2a57e77de94AC on both contracts. On the
FeeVault it can veto a pending bind during its timelock (vetoBind); a veto never moves
funds. On the QuoteRegistry it can disable a quote for new launches. It can never enable
anything. The owner can replace or remove it with setGuardian on each contract.
Attestors
None are registered at launch (attestorThreshold = 0), so no social-account escrow can be
bound or claimed. When attestors are added:
- k of n together can propose a bind for a social escrow (subject to the timelock and vetoes).
- Any one can veto a pending bind.
- Each one can decrypt launch hints on its own (hints are threshold 1, not threshold-encrypted), so each knows which accounts have escrows.
Railgun adapter owner
May only set the maximum accepted shield fee (setMaxFeeBps, hard cap 1%), set the sanctions
oracle that screens each shield's submitter (setSanctionsList; currently the Chainalysis oracle,
address(0) turns screening off), and pause / unpause new shields. Cannot take funds.
While paused, or if the oracle reverts or lists the submitter, Railgun claims revert and funds
stay in the vault.
QuoteRegistry owner and guardian
The owner (Ownable2Step; currently the same single EOA, no timelock) manages Tier 1 quotes (setQuote),
pre-approves exact Tier-2 configs (setTier2Approval), removes quotes and sets the factory and
guardian. The registry holds the factory's admin role, which only allows setQuoteToken.
| Can | Cannot |
|---|---|
| Allow or delist quotes for new launches; set tick bounds | Touch existing pools, liquidity or balances |
| Swap a quote's executor, route, feed, deviation and cap | On the beneficiary-signed path, take more than the signed minOut: the vault requires an exact input pull and USDT out ≥ minOut. On the creator path the bound is oracle-derived from the owner's own configuration (see the FeeVault risk above) |
| Remove a route (consolidation of that asset then reverts; claims in that asset still work) | Redirect consolidated USDT; it is always credited to the same id |
The guardian may only disable a quote for new launches. It can never enable anything.
Per-coin roles
Token admin
Chosen by the creator, can be renounced (address(0)).
| Can | Cannot |
|---|---|
| Update image and metadata | Mint, burn others' tokens, pause, blacklist |
lowerFees (never below 1%) | Raise the fee |
| Hand over or renounce the role | Touch liquidity, fees or the beneficiary |
Creator
| Can | Cannot |
|---|---|
| Hold a copy of the stealth key until the beneficiary rotates (stealth kits) | Change the beneficiary id |
| Trigger an oracle-bounded consolidation of its own launch's credit (a pro-rata share of the beneficiary's balance that every owner withdrawal shrinks), at least 1 USDT per swap | Touch donations, other launches' fees, or anything credited after the owner withdrew |
| Shield that USDT to the beneficiary's next pre-registered template | Choose where consolidated funds go; use templates registered before a rotation or rebind (they are discarded) |
Off-chain trust
| Service | You trust it for | You do not trust it for |
|---|---|---|
| Relayer | Liveness, not logging your IP | Correctness: it cannot change a signed claim or its own fee |
| Attestors | Honest OAuth checks, not colluding (k of n), keeping hint keys safe | Custody: they never hold your key |
| Indexer | Correct display data | Funds |
| Web app host | Serving unmodified code | The claim link secret (it stays in the URL fragment); which escrows you own (escrow coin pages are not prefetched) |
| RPC provider | Correct chain data | Learning which id you act for: the app makes no id-specific reads (nonces come from the relayer index, prices from one fixed batch of unit oracle quotes) |
Serving modified code would be an attack on the web app host. Self-hosting the app or verifying release hashes reduces this risk.