Description
The vault stores its allowed-depositor allowlist as an unbounded Vec<Address> under StorageKey::DepositorList. Both set_allowed_depositor (contracts/vault/src/lib.rs:496) and the convenience alias add_address (:1251) push_back a new entry with no size limit, and is_authorized_depositor (:386) plus is_authorized_depositor-backed deposit iterate the list via list.contains(&caller). An owner who keeps adding depositors (or a buggy script) can grow this Vec until reading or scanning it during deposit exceeds Soroban's per-transaction resource budget, bricking the deposit path and the get_allowed_depositors / get_allowlist views.
This mirrors the bounded-batch hardening already applied elsewhere (vault MAX_BATCH_SIZE = 50, revenue-pool batch_distribute cap documented in SECURITY.md). This issue adds an explicit cap on the allowlist size.
Requirements and context
Functional
- Introduce a constant, e.g.
pub const MAX_ALLOWED_DEPOSITORS: u32 = 100; (choose a value and justify it against Soroban limits, like the existing MAX_BATCH_SIZE rationale).
- In
set_allowed_depositor and add_address, reject an addition that would exceed the cap with a new VaultError::AllowlistFull (only when the address is not already present — re-adding an existing entry is a no-op today and must stay so).
- Keep the clear paths (
clear_allowed_depositors at :526, clear_all at :1270, and set_allowed_depositor(None)) working so the owner can always shrink the list.
- Document the bound: a depositor set larger than the cap should use a different access pattern (e.g. owner-as-sole-depositor with off-chain authorization).
Non-functional / repo conventions
- No change to the
deposit authorization semantics beyond the new cap; owner is always authorized (is_authorized_depositor returns true for owner).
- Update
SECURITY.md (Vault-Specific Risks: "Batch operations respect individual limits" and unbounded-growth note), docs/interfaces/vault.json (new error code + set_allowed_depositor panic list), and contracts/vault/STORAGE.md / ACCESS_CONTROL.md as relevant.
- Keep WASM within budget (
scripts/check-wasm-size.sh).
Acceptance criteria
Suggested execution
1. Fork the repo and create a branch
git checkout -b fix/vault-bound-allowlist
2. Implement changes
contracts/vault/src/lib.rs — add MAX_ALLOWED_DEPOSITORS, VaultError::AllowlistFull, and length checks in set_allowed_depositor and add_address.
- Update
docs/interfaces/vault.json, SECURITY.md, contracts/vault/STORAGE.md / ACCESS_CONTROL.md.
3. Write/extend tests in contracts/vault/src/test.rs:
- add
MAX_ALLOWED_DEPOSITORS distinct depositors (all succeed), assert get_allowed_depositors().len() equals the cap;
- the next distinct add returns
AllowlistFull;
- re-adding an already-present address at the cap is a no-op success;
clear_allowed_depositors empties the list and a subsequent add succeeds again;
- owner can still deposit when the list is full.
4. Test and commit
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace
./scripts/check-wasm-size.sh
./scripts/coverage.sh
Example commit message
fix(vault): bound allowed-depositors list with MAX_ALLOWED_DEPOSITORS
Guidelines
- Coverage must stay >= 95% (
scripts/coverage.sh), CI-enforced via .github/workflows/coverage.yml.
- NatSpec-style
/// docs on the touched entrypoints; keep docs/interfaces/vault.json and SECURITY.md authoritative.
- Include a short note on the threat addressed (storage-exhaustion DoS of the deposit path) in the PR description.
- Timeframe: 96 hours.
Description
The vault stores its allowed-depositor allowlist as an unbounded
Vec<Address>underStorageKey::DepositorList. Bothset_allowed_depositor(contracts/vault/src/lib.rs:496) and the convenience aliasadd_address(:1251)push_backa new entry with no size limit, andis_authorized_depositor(:386) plusis_authorized_depositor-backeddeposititerate the list vialist.contains(&caller). An owner who keeps adding depositors (or a buggy script) can grow thisVecuntil reading or scanning it duringdepositexceeds Soroban's per-transaction resource budget, bricking the deposit path and theget_allowed_depositors/get_allowlistviews.This mirrors the bounded-batch hardening already applied elsewhere (vault
MAX_BATCH_SIZE = 50, revenue-poolbatch_distributecap documented inSECURITY.md). This issue adds an explicit cap on the allowlist size.Requirements and context
Functional
pub const MAX_ALLOWED_DEPOSITORS: u32 = 100;(choose a value and justify it against Soroban limits, like the existingMAX_BATCH_SIZErationale).set_allowed_depositorandadd_address, reject an addition that would exceed the cap with a newVaultError::AllowlistFull(only when the address is not already present — re-adding an existing entry is a no-op today and must stay so).clear_allowed_depositorsat:526,clear_allat:1270, andset_allowed_depositor(None)) working so the owner can always shrink the list.Non-functional / repo conventions
depositauthorization semantics beyond the new cap; owner is always authorized (is_authorized_depositorreturnstruefor owner).SECURITY.md(Vault-Specific Risks: "Batch operations respect individual limits" and unbounded-growth note),docs/interfaces/vault.json(new error code +set_allowed_depositorpanic list), andcontracts/vault/STORAGE.md/ACCESS_CONTROL.mdas relevant.scripts/check-wasm-size.sh).Acceptance criteria
MAX_ALLOWED_DEPOSITORSconstant added and enforced in bothset_allowed_depositorandadd_address.VaultError::AllowlistFull; re-adding an existing address remains a no-op.docs/interfaces/vault.json;SECURITY.mdupdated with the bound and rationale.scripts/coverage.sh).Suggested execution
1. Fork the repo and create a branch
2. Implement changes
contracts/vault/src/lib.rs— addMAX_ALLOWED_DEPOSITORS,VaultError::AllowlistFull, and length checks inset_allowed_depositorandadd_address.docs/interfaces/vault.json,SECURITY.md,contracts/vault/STORAGE.md/ACCESS_CONTROL.md.3. Write/extend tests in
contracts/vault/src/test.rs:MAX_ALLOWED_DEPOSITORSdistinct depositors (all succeed), assertget_allowed_depositors().len()equals the cap;AllowlistFull;clear_allowed_depositorsempties the list and a subsequent add succeeds again;4. Test and commit
cargo fmt --all -- --check cargo clippy --all-targets --all-features -- -D warnings cargo test --workspace ./scripts/check-wasm-size.sh ./scripts/coverage.shExample commit message
Guidelines
scripts/coverage.sh), CI-enforced via.github/workflows/coverage.yml.///docs on the touched entrypoints; keepdocs/interfaces/vault.jsonandSECURITY.mdauthoritative.