Status: Living artifact (canonical threat register)
Last Updated: 2026-06-01
Scope: Bond operations (credence_bond), delegation (credence_delegation), treasury guardrails
This document enumerates security threats to the Credence bond and delegation system, mitigations applied, and test fixtures that validate each mitigation. Each threat row is referenced by test comments via /// THREAT: T-XXX to establish bidirectional traceability.
| ID | Asset | Attacker | Attack Vector | Impact | Mitigation | Test Fixture(s) | Status |
|---|---|---|---|---|---|---|---|
| T-001 | Bond principal | Unauthorized user | Direct slash via unsigned call | Loss of bonded funds | Role-based access control; require_auth on admin slash |
contracts/credence_bond/src/test_access_control.rs::test_only_admin_can_slash |
✅ Covered |
| T-002 | Bond principal | Unauthorized user | Modify bond parameters (duration, tier, etc.) without authorization | Unfair bond terms | Admin-only config setters with role checks | contracts/credence_bond/src/test_access_control.rs::test_unauthorized_config_changes |
✅ Covered |
| T-003 | Bonded funds | Unauthorized user | Create bonds on behalf of other identities | Fraudulent lockup | Identity-first bond creation; nonce tied to identity | contracts/credence_bond/src/test_create_bond.rs::test_create_bond_only_for_self |
✅ Covered |
| T-004 | Bond arithmetic state | Attacker (overflow) | Craft maximum bond + top-ups to cause i128 overflow | Funds stolen via underflow bypass | Checked arithmetic (checked_add, checked_sub); panic on overflow |
contracts/credence_bond/src/security/test_arithmetic.rs::test_i128_overflow_on_top_up |
✅ Covered |
| T-005 | Bond arithmetic state | Attacker (underflow) | Craft slashes + withdrawals to cause i128 underflow | Negative balances; theft | Checked arithmetic; underflow panics | contracts/credence_bond/src/security/test_arithmetic.rs::test_withdrawal_exceeds_available_balance |
✅ Covered |
| T-006 | Bond arithmetic state | Attacker | Timestamp duration overflow (u64::MAX + duration) | Bond expiry bypass | Checked addition on start + duration; panic if overflows |
contracts/credence_bond/src/security/test_arithmetic.rs::test_u64_overflow_on_duration_extension |
✅ Covered |
| T-007 | Bond invariant (I2) | Attacker | Slash bond for amount > principal | State corruption: slashed > bonded | Hard cap: min(slash_amount, bonded_amount) |
contracts/credence_bond/src/test_slashing.rs::test_slashing_exceeds_bonded_amount |
✅ Covered |
| T-008 | Bond invariant (I4) | Attacker | Withdrawal > bonded - slashed | Negative bonded; stolen funds | Checked subtraction: available = bonded - slashed | contracts/credence_bond/src/test_withdraw_bond.rs::test_withdrawal_exceeds_available_balance |
✅ Covered |
| T-009 | Fee collection | Reentrancy attacker | Reenter withdraw_bond during fee callback to drain treasury | Protocol fee theft | Reentrancy guard + checks-effects-interactions; state updated before callback | contracts/credence_bond/src/test_reentrancy.rs::test_reentrancy_in_fee_collection |
✅ Covered |
| T-010 | Bond state | Reentrancy attacker | Reenter slash_bond during transfer callback | Double slash same bond; state corruption | Reentrancy guard; atomic slash then transfer | contracts/credence_bond/src/test_reentrancy.rs::test_reentrancy_slash_bond |
✅ Covered |
| T-011 | Nonce sequencing | Replay attacker | Replay signed attestation (nonce + deadline + data) | Duplicate attestation; false evidence | Nonce incremented atomically; second call fails "invalid nonce" | contracts/credence_bond/src/test_replay_prevention.rs::test_replay_prevention_nonce_invalidation |
✅ Covered |
| T-012 | Nonce sequencing | Replay attacker | Reorder attestations to consume nonce out-of-order | Early attestations rejected; trust broken | Strict nonce matching; out-of-order calls rejected | contracts/credence_bond/src/test_replay_prevention.rs::test_out_of_order_attestations_rejected |
✅ Covered |
| T-013 | Contract domain | Cross-chain attacker | Replay nonce/deadline pair across different deployed contracts | Fund theft from sibling deployment | Contract ID validated against current address | contracts/credence_bond/src/test_replay_prevention.rs::test_contract_id_domain_separation |
✅ Covered |
| T-014 | Attestation integrity | Unauthorized attester | Add attestations without admin registration | False claims recorded | Only registered attesters pass require_auth |
contracts/credence_bond/src/test_attester.rs::test_unregistered_attester_rejected |
✅ Covered |
| T-015 | Attestation integrity | Attester | Duplicate attestations for same subject + data | Inflated weight; unfair tier | Duplicate check: (verifier, subject, data) unique key |
contracts/credence_bond/src/test_attester.rs::test_duplicate_attestation_rejected |
✅ Covered |
| T-016 | Attestation weight | Attacker | Craft negative attestation weight to bypass invariant I1 | Negative total weight; broken tier system | Weight sum validated ≥ 0 after every attestation |
contracts/credence_bond/src/test_weighted_attestation.rs::test_attestation_weight_sum_non_negative |
✅ Covered |
| T-017 | Tier assignment | Attacker | Threshold not validated; arbitrary tier assignment | Over-leveraged bonds; default | Tier computed from weight; thresholds fixed by admin | contracts/credence_bond/src/test_tiered_bond.rs::test_tier_computed_from_threshold |
✅ Covered |
| T-018 | Rolling bond invariant (I3) | Attacker | Request withdrawal on fixed-duration bond | Invalid state; withdrawal becomes claimable when it shouldn't | Fixed bonds reject request_withdrawal with error |
contracts/credence_bond/src/test_rolling_bond.rs::test_fixed_bond_withdrawal_request_rejected |
✅ Covered |
| T-019 | Rolling bond invariant (I6) | Attacker | Set notice period > bond duration | Notice never clears; funds locked indefinitely | Validation notice_period <= bond_duration at creation |
contracts/credence_bond/src/test_rolling_bond.rs::test_notice_period_bounded |
✅ Covered |
| T-020 | Early exit penalty | Attacker | Exit early without penalty | Penalty evasion; unfair exit | Penalty deducted from available balance before withdrawal | contracts/credence_bond/src/test_early_exit_penalty.rs::test_early_exit_penalty_deduction |
✅ Covered |
| T-021 | Supply cap | Attacker | Create bonds totaling > supply cap | Excessive leverage | Supply cap enforced on bond creation; rejected if exceeded | contracts/credence_bond/src/test_supply_cap.rs::test_supply_cap_enforcement |
✅ Covered |
| T-022 | Cooldown timing | Attacker | Withdraw within cooldown period | Rapid re-entry; unfair advantage | Cooldown recorded; withdrawal rejected if still in cooldown | contracts/credence_bond/src/test_cooldown.rs::test_withdrawal_cooldown_enforcement |
✅ Covered |
| T-023 | Grace window (nonce) | Attacker | Submit attestation after grace window expiration | Old attestations reused; stale evidence | Deadline checked before nonce consumed; deadline < now panics | contracts/credence_bond/src/test_grace_period.rs::test_deadline_expiration_rejects_attestation |
✅ Covered |
| T-024 | Same-ledger invariant | Sandwich attacker | Slash immediately after bond creation (same ledger) | Unfair liquidation; slashed without chance to adjust | Same-ledger guard: slash rejected if last_collateral_increase in current ledger |
contracts/credence_bond/src/test_same_ledger_liquidation_guard.rs::test_slash_rejected_in_same_ledger |
✅ Covered |
| T-025 | Bond lifecycle | Attacker | Claim withdrawal on fixed-duration bond before maturity | Premature liquidation | Only rolling bonds allow claims; fixed bonds return 0 claimable | contracts/credence_bond/src/test_claim.rs::test_fixed_bond_no_claim_before_maturity |
✅ Covered |
| T-026 | Emergency mode | Malicious admin | Activate emergency mode to freeze all bonds indefinitely | Denial of service; funds locked | Emergency mode is toggle (can be disabled); gov guard | contracts/credence_bond/src/test_emergency.rs::test_emergency_mode_can_be_disabled |
✅ Covered |
| T-027 | Emergency withdrawal | Unauthorized user | Call emergency_withdraw during non-emergency | Unauthorized fund extraction | Guard: require_emergency_mode or admin-only |
contracts/credence_bond/src/test_emergency.rs::test_emergency_withdraw_requires_emergency_mode |
✅ Covered |
| T-028 | Fee collection | Admin | Collect fees multiple times for same period | Double-fee theft | Fee collection counter incremented; duplicate calls rejected | contracts/credence_bond/src/test_fees.rs::test_fee_collection_prevents_double_withdraw |
✅ Covered |
| T-029 | Pause mechanism | Attacker | Bypass pause to execute state-changing calls | Paused contract compromise | All state-changing calls check !paused() guard |
contracts/credence_bond/src/test_pausable.rs::test_state_changes_blocked_when_paused |
✅ Covered |
| T-030 | Pause signer | Attacker | Pause contract without valid multi-sig threshold | Unauthorized freeze | Pause requires threshold of authorized signers | contracts/credence_delegation/src/test_pause_signer_invariant.rs::test_pause_requires_threshold_signers |
✅ Covered |
| T-031 | Verifier management | Unauthorized user | Add/remove verifiers without admin | Broken trust chain | Verifier add/remove admin-only | contracts/credence_bond/src/test_verifier.rs::test_unauthorized_verifier_modification |
✅ Covered |
| T-032 | Governance attack | Low-stake attacker | Propose slash with minimal governance stake | Frivolous slashes; DoS | Governance proposal requires minimum bond or stake | contracts/credence_bond/src/integration/test_governance.rs::test_governance_proposal_requires_stake |
✅ Covered |
| T-033 | Governance execution | Attacker | Execute governance slash after voting period closes | Stale execution; unfair | Execution window validated; expired proposals rejected | contracts/credence_bond/src/integration/test_governance.rs::test_execution_window_expired |
✅ Covered |
| T-034 | Batch atomicity | Attacker | Create batch with one failing sub-operation; partial state update | Inconsistent state | Batch operations atomic: all-or-nothing via revert | contracts/credence_bond/src/test_batch.rs::test_batch_atomicity_on_failure |
✅ Covered |
| T-035 | Batch pagination | Attacker (pagination) | Query claims with skip >= total; bypass claim cap | Unlimited claim extraction | Pagination guards: skip validated < total | contracts/credence_bond/src/test_claim_pagination.rs::test_claim_pagination_skip_validation |
✅ Covered |
| T-036 | Basis point math | Attacker | Craft fees/penalties with rounding down to 0 | Fee bypass; penalty evasion | BPS denominator validated; rounding tests explicit | contracts/credence_bond/src/test_bps_denominator.rs::test_bps_rounding_floor |
✅ Covered |
| T-037 | Zero address | Attacker | Set bond token or treasury to address(0) | Transfers to void; state corruption | Zero address guards on parameter setters | contracts/credence_bond/src/test_zero_address.rs::test_zero_address_rejected_on_token_set |
✅ Covered |
| T-038 | Delegation TTL | Attacker | Replay a delegation after it expires | Unauthorized delegation; re-entry | Delegation expiry checked before execution | contracts/credence_delegation/src/test_delegation_ttl.rs::test_expired_delegation_rejected |
✅ Covered |
| T-039 | Domain separation (delegation) | Cross-contract attacker | Replay delegation across different contract domains | Sibling contract compromise | Domain separator in signature; validated on execution | contracts/credence_delegation/src/test_domain_separation.rs::test_domain_separation_prevents_replay |
✅ Covered |
| T-040 | Token custody | External token | Receive fee-on-transfer token; fee charged twice | Protocol fee reduced; state mismatch | Safe transfer helpers; balance delta verified | contracts/credence_bond/src/test_token_custody.rs::test_fee_on_transfer_token_rejected |
✅ Covered |
| T-041 | Attestation revocation | Unauthorized user | Revoke attestation without admin status | Trust chain broken; false negation | Revocation requires original verifier | contracts/credence_bond/src/test_attester.rs::test_revoke_attestation_requires_original_verifier |
✅ Covered |
| T-042 | Evidence preservation | Admin | Delete evidence to hide misbehavior | Audit trail lost | Evidence storage immutable after creation | contracts/credence_bond/src/test_evidence.rs::test_evidence_immutable_after_creation |
✅ Covered |
| T-043 | Bond lockup gate | Attacker | Claim locked bond before lockup expires | Premature withdrawal; theft | Lockup expiry validated; claim rejected if locked | contracts/credence_bond/tests/test_access_control.rs::test_lockup_gate_enforcement |
✅ Covered |
| T-044 | Ownership transfer | Attacker | Hijack bond by changing identity owner | Unauthorized access | Ownership transfer requires current owner signature | contracts/credence_bond/src/test_ownership_transfer.rs::test_ownership_transfer_requires_current_owner_signature |
✅ Covered |
| T-045 | Treasury slippage | Attacker | Craft liquidation order to extract more than queued | Arbitrage theft | Withdrawal guardrails; slippage cap enforced | contracts/credence_treasury/src/test_withdrawal_guardrails.rs::test_slippage_bounds_enforced |
✅ Covered |
| T-046 | Flash loan attack | Attacker | Borrow from treasury, manipulate price, repay for profit | Protocol fee loss; treasury drained | Flash loan fee charged; oracle checks | contracts/credence_treasury/src/test_flash_loan.rs::test_flash_loan_fee_enforced |
✅ Covered |
| T-047 | Decimal normalization | Attacker | Craft tokens with unusual decimals to bypass amount checks | Rounding errors; theft | Decimal normalization applied consistently | contracts/credence_bond/src/test_decimal_normalization.rs::test_decimal_normalization_correctness |
✅ Covered |
| T-048 | Duration validation | Attacker | Set zero or negative bond duration | Maturity bypass; lockup shortcut | Duration > 0 validated at creation | contracts/credence_bond/src/test_duration_validation.rs::test_zero_duration_rejected |
✅ Covered |
| T-049 | Immutable config | Attacker | Modify config after contract deployed | Governance violated; parameters changed unfairly | Config setters locked after init | contracts/credence_bond/src/test_immutable_config.rs::test_config_immutable_post_init |
✅ Covered |
| T-050 | Long-horizon bonds | Attacker | Create bonds with extreme durations (years) | Maturity computation overflow; lock forever | Duration checked < u64::MAX / 2 | contracts/credence_bond/src/test_long_horizon.rs::test_extreme_duration_validation |
✅ Covered |
| Module | Threats | Test Commands |
|---|---|---|
| Access Control | T-001, T-002, T-003, T-014, T-031 | cargo test -p credence_bond test_access_control |
| Arithmetic Safety | T-004, T-005, T-006 | cargo test -p credence_bond security::test_arithmetic |
| Slashing & Invariants | T-007, T-008, T-016, T-017 | cargo test -p credence_bond test_slashing test_weighted_attestation |
| Reentrancy | T-009, T-010 | cargo test -p credence_bond test_reentrancy |
| Replay Prevention | T-011, T-012, T-013 | cargo test -p credence_bond test_replay_prevention |
| Attestation | T-014, T-015, T-016, T-041 | cargo test -p credence_bond test_attester test_weighted_attestation |
| Bond Lifecycle | T-018, T-019, T-020, T-022, T-025 | cargo test -p credence_bond test_rolling_bond test_claim test_early_exit_penalty |
| Same-Ledger Guard | T-024 | cargo test -p credence_bond test_same_ledger_liquidation_guard |
| Emergency & Pause | T-026, T-027, T-029 | cargo test -p credence_bond test_emergency test_pausable |
| Governance | T-032, T-033 | cargo test -p credence_bond integration::test_governance |
| Batch Operations | T-034, T-035 | cargo test -p credence_bond test_batch test_claim_pagination |
| Configuration & Params | T-006, T-023, T-037, T-048, T-050 | cargo test -p credence_bond test_parameters test_duration_validation |
| Fees & Penalties | T-028, T-036, T-040 | cargo test -p credence_bond test_fees test_bps_denominator test_token_custody |
| Evidence & Audit | T-042 | cargo test -p credence_bond test_evidence |
| Advanced | T-043, T-044, T-047, T-049 | cargo test -p credence_bond test_ownership_transfer test_decimal_normalization test_immutable_config |
| Module | Threats | Test Commands |
|---|---|---|
| Pause Mechanism | T-030 | cargo test -p credence_delegation test_pause_signer_invariant |
| Delegation TTL | T-038 | cargo test -p credence_delegation test_delegation_ttl |
| Domain Separation | T-039 | cargo test -p credence_delegation test_domain_separation |
| Module | Threats | Test Commands |
|---|---|---|
| Slippage & Guardrails | T-045 | cargo test -p credence_treasury test_withdrawal_guardrails |
| Flash Loans | T-046 | cargo test -p credence_treasury test_flash_loan |
Each test function must begin with a comment block listing the threats it covers:
/// THREAT: T-001, T-002
/// Validates that role-based access control prevents unauthorized admin operations.
#[test]
fn test_only_admin_can_slash() {
// test body
}- One threat per line: If a test covers multiple threats, list each on its own line after
THREAT:. - Top of test function: Threat annotation must appear immediately before
#[test]or at the very top of the function. - Format:
/// THREAT: T-NNN(comment style matches module convention). - Bidirectional traceability: The threat registry row points to the test; the test comments point back via threat ID.
- Assign next ID (e.g., T-051).
- Fill in row: asset, attacker profile, vector, impact, mitigation, test fixture.
- Create or update test with threat annotation.
- Run
cargo test threats_linkto verify the test exists. - Commit with message:
docs(contracts): add threat T-NNN — [description].
- Locate threat row by ID.
- Update mitigation column.
- Verify test still passes.
- If test name changes, update test fixture column.
- Commit with message:
docs(contracts): revise T-NNN mitigation — [reason].
- Mark row as
⚠ Archivedin Status column. - Add a note: "Archived: [reason], replaced by T-XXX on [date]."
- Keep row in table for historical audit trail.
- Do not remove tests (they provide regression protection).
Bidirectional consistency is enforced via the tests/threats_link.rs test:
- ✅ Parses THREATS.md table.
- ✅ Verifies each referenced test exists.
- ✅ Verifies each test begins with a
/// THREAT: T-NNNcomment. - ✅ Ensures threat IDs and test mappings match.
- ✅ Fails if a threat row references a non-existent test.
- ✅ Fails if a test is missing threat annotation.
Usage:
cargo test -p credence_bond threats_link -- --nocapture- Bond Invariants — Formal invariants guarding bond state.
- Security — Overflow-safe arithmetic, replay prevention, reentrancy guards.
- SECURITY.md — Access control matrix and role hierarchy.
- SECURITY_ANALYSIS.md — Arithmetic security deep dive.