Security
This page summarizes the security measures built into the Catpound vault.
Built-In Protections
SafeMath
All arithmetic operations in the vault use SafeMath (checked math). Overflow and underflow cause the transaction to revert rather than wrapping silently. This prevents a broad class of bugs where unexpected numeric behavior could lead to loss of funds.
Reentrancy Guard
The vault uses a STANDARD-level reentrancy guard (the strictest level). No external call can re-enter the vault during execution. This prevents attacks where a malicious contract could call back into the vault during a transfer to manipulate state.
Donation-Proof Accounting
The vault tracks totalAssets as a separate storage variable rather than reading its on-chain MOTO balance. This means:
- Sending MOTO directly to the vault contract does not increase
totalAssets - The share price is only affected by deposits, withdrawals, and compound operations
- A "donation attack" (inflating share price by sending tokens directly) is ineffective
Dead Shares
On the first deposit, 1,000 cpMOTO shares are permanently burned. This prevents a share price manipulation attack where an attacker could:
- Deposit a small amount to be the sole shareholder
- Donate a large amount to inflate the share price
- Cause subsequent depositors to receive 0 shares due to rounding
With 1,000 dead shares always in circulation, this attack becomes economically impractical. V4.3 additionally requires the first deposit to be at least 100 MOTO (see above).
Checks-Effects-Interactions (CEI) Pattern
All vault functions follow the CEI pattern:
- Checks: Validate inputs and conditions
- Effects: Update internal state (balances, counters, flags)
- Interactions: Make external calls (token transfers, MotoChef operations)
This ordering prevents state inconsistencies if an external call reverts.
Hard Caps
Critical parameters have hardcoded ceilings in the contract that cannot be changed by the admin:
| Parameter | Hard Cap |
|---|---|
| Maximum exit fee per tier | 10% (1,000 BPS) |
| Maximum protocol fee per tier | 10% (1,000 BPS) |
| Maximum staked NFTs per user | 10 |
| Maximum tier ID | 7 (tiers 0–7) |
| MotoChef migration timelock | 144 blocks (~24 hours) |
Anti-Gaming: NFT Staking
The vault tracks a stakeBlock when NFTs are staked. If stakeBlock > lastReinvestBlock, the NFT tier contribution is temporarily suppressed until the next compound cycle completes. This prevents users from staking NFTs right before a compound to reduce fees, then immediately unstaking.
Your NFT tier "activates" at the next compound cycle after staking.
Quantum-Resistant Signatures
The vault contract runs on OPNet, which supports ML-DSA (FIPS 204) digital signatures alongside ECDSA and Schnorr. This provides forward-looking protection against quantum computing threats.
Ownership Model
The vault uses a two-step ownership transfer:
- Current owner proposes a new owner (
transferOwnership) - New owner must explicitly accept (
acceptOwnership)
This prevents accidental or malicious ownership transfers. The pending transfer can be cancelled at any time before acceptance.
Emergency Controls
The vault owner has the following emergency capabilities:
- Pause deposits: Blocks new deposits while withdrawals continue to work
- Emergency unstake: Force-unstakes everything from MotoChef, making all MOTO liquid (and clears the
stakedInChefflag) - MotoChef migration: Propose moving to a new staking contract with a 144-block timelock
These are safety valves for responding to upstream issues with MotoChef or other emergency situations.