Security
Audit status, timelocks, the multisig, upgradeability policy and the bug bounty.
On this page
The honest summary: nothing has been audited because nothing has been deployed. This page describes the controls the deployment will ship with and states plainly which of them currently have evidence behind them.
Audit status
| Item | Status |
|---|---|
| External audit | Not started. No firm engaged. |
| Internal review | Interfaces published for comment |
| Formal verification | Planned for the distributor accumulator only |
| Testnet deployment | Not yet |
| Verified source on Etherscan | Will publish at deployment |
| Attestation of reserve holdings | First one due after the first batch |
The distributor is the priority for verification because its accumulator arithmetic is where a rounding error becomes an over-allocation against the reserve, and an over-allocation is the one failure that cannot be undone by pausing.
Timelock
Every privileged action routes through a timelock with a 48-hour minimum delay. Queued actions are visible on-chain from the moment they are proposed, which means holders have two days to exit before any parameter change takes effect.
| Action | Delay |
|---|---|
| Fee parameter change | 48 hours |
| Allocation change | 48 hours |
| Adapter or broker rotation | 7 days |
| Exclusion list addition | 48 hours |
| Emergency pause | Immediate, cannot move funds |
| Unpause | 48 hours |
The asymmetry between pause and unpause is intentional. Stopping is safe and should be fast; restarting is a decision and should be slow.
Multisig
The timelock is controlled by a 3-of-5 multisig. Signer identities are published at deployment, keys are held on separate hardware in separate locations, and no signer holds a second signing role.
What the multisig cannot do is the part worth reading:
- It cannot mint BANK. There is no mint function.
- It cannot move ETH out of the router to an arbitrary address.
- It cannot transfer HOOD shares out of the reserve except to the distributor.
- It cannot zero or reduce a holder’s unclaimed entitlement.
- It cannot unlock liquidity before the lock expires.
Upgradeability policy
| Contract | Upgradeable | Rationale |
|---|---|---|
| BankhoodToken | No | Holders cannot exit the token itself, so it gets no proxy. |
| Distributor | No | Holds entitlement accounting. A migration would require re-deriving every balance. |
| FeeRouter | Parameters only | Destinations are fixed; only the split is adjustable within bounds. |
| ReserveVault | No | Custody accounting must be append-only to stay auditable. |
| BrokerageAdapter | Replaceable | It is off-chain infrastructure. Replacement takes 7 days. |
The pattern is that anything holding accounting is immutable and anything holding an external relationship is replaceable on a long delay.
Invariants
These are the properties tests and verification target. A violation of any of them is a critical bug.
- Sum of all unclaimed entitlements plus all claimed shares never exceeds
ReserveVault.totalShares(). accSharesPerTokenis monotonically non-decreasing.- A claim can never increase the caller’s unclaimed balance or decrease another address’s.
- A transfer settles both parties before balances change, so no accrual is created or destroyed by moving tokens.
reportFillcredits a givenorderIdat most once.- Excluded addresses never accrue, and taxable supply always equals total supply minus excluded balances.
Bug bounty
| Severity | Reward | Example |
|---|---|---|
| Critical | Up to 10% of funds at risk, capped at $250,000 | Drain the reserve or over-allocate entitlements |
| High | $25,000 | Bypass the claim cooldown or accrue on an excluded balance |
| Medium | $5,000 | Grief distributions or force purchases to stall |
| Low | $1,000 | Incorrect event data that misleads the indexer |
The programme opens with the testnet deployment. Until there is deployed code, there is nothing to pay a bounty on, and any bounty page claiming otherwise is not ours.
Reporting a vulnerability
Report privately first. Do not open a public issue, do not post a proof of concept, and do not test against mainnet contracts once they exist. A report should include the affected contract, the invariant broken, and a minimal reproduction.
Response targets are 24 hours for acknowledgement and 72 hours for triage, with a public post-mortem after any fix ships. If a fix requires a pause, the pause happens first and the explanation follows — see governance.