Security
Security architecture and trust assumptions for the Symbiotic multi-provider template.
Shared Trust Model
| Entity | Trust Level | Notes |
|---|---|---|
| Settlement | Trusted | Symbiotic contract for BLS signature verification |
| Authorized Submitters | Semi-trusted | Whitelisted addresses that submit proofs; cannot forge signatures but can grief (spam invalid proofs) |
| Owner | Trusted | Admin with pause/unpause, submitter management |
| External users | Untrusted | Cannot call privileged functions directly |
Symbiotic Security Layer
- Operators stake and register BLS public keys via
KeyRegistry - Settlement contract verifies BLS quorum before accepting proofs
- Slashing handled by Symbiotic core contracts (production)
Webhook Authentication
Webhooks between OZ Monitor and operators use HMAC-SHA256:
- Monitor computes
HMAC-SHA256(secret, body + timestamp) - Signature sent in
X-Signatureheader - Timestamp (ms since epoch) sent in
X-Timestampheader - Operator rejects invalid/missing signatures or expired timestamps (HTTP 401)
Secrets must be at least 32 characters. See CLI Reference for config details.
LayerZero DVN Security
Trust assumptions specific to the SymbioticLayerZeroDVN contract.
| Entity | Trust Level | Notes |
|---|---|---|
| SendUln302 | Trusted | LayerZero's send library; only caller for assignJob |
Access Control
Source Chain
| Function | Caller | Purpose |
|---|---|---|
assignJob | SendUln302 only | Register verification job, emit event |
getFee | Anyone | Query verification fee (view) |
Destination Chain
| Function | Caller | Purpose |
|---|---|---|
submitProof | Authorized submitters | Submit signed Merkle proof for verification |
Admin
| Function | Caller | Purpose |
|---|---|---|
addSubmitter / removeSubmitter | Owner | Manage submitter whitelist |
setBaseFee | Owner | Update verification fee |
pause / unpause | Owner | Emergency controls |
withdraw | Owner | Recover ETH (force-sent or accidental) |
transferOwnership | Owner | Transfer admin rights |
Invariants
- Leaf monotonicity:
verifiedLeaves[leaf]transitionsfalse -> trueonly, never back - Root monotonicity:
verifiedRoots[root]transitionsfalse -> trueonly, never back - Signature requirement: Uncached roots require valid BLS quorum from Settlement
- Packet header integrity: Verified packets have exactly 81 bytes and correct
dstEid - No ETH custody: Contract does not collect fees;
assignJobrejectsmsg.value > 0
Deployment Modes
| Mode | sendUln | receiveUln | settlement | Use case |
|---|---|---|---|---|
| Source only | Set | Zero | Zero | Emit JobAssigned events |
| Destination only | Zero | Set | Set | Verify proofs, call ReceiveUln |
| Bidirectional | Set | Set | Set | Both functions on same chain |
What the DVN Does NOT Do
- Fee custody: Fees handled by LayerZero's fee accounting
- Signature generation: BLS signing happens off-chain via Symbiotic Relay
- Slashing: Handled by Symbiotic core contracts
Chainlink CCV Security
Trust assumptions specific to the SymbioticCCV contract.
Access Control
| Function | Caller | Purpose |
|---|---|---|
forwardToVerifier | OnRamp | Source-chain hook for CCV registration |
verifyMessage | OffRamp | Destination verification hook |
getFee | Anyone | Quote verification fee (view) |
Invariants
CCV verification requires:
- Valid BLS quorum signature from Settlement
- Correct message ID derivation
- Epoch freshness (reverts with
EpochTooStaleif settlement data is stale)
External Dependencies
| Dependency | Version | Purpose |
|---|---|---|
@openzeppelin/contracts | 5.x | MerkleProof verification |
@symbioticfi/relay-contracts | - | Settlement base contracts |
| LayerZero V2 | - | ILayerZeroDVN interface |
| Chainlink CCIP | - | CCV interfaces (ICrossChainVerifierV1) |