Skip to content

Latest commit

 

History

History
79 lines (56 loc) · 2.79 KB

File metadata and controls

79 lines (56 loc) · 2.79 KB

S004 — Ledger Entry Size Risk

  • Category: storage_limits
  • Severity: Medium
  • Rule name: ledger_size

What it detects

S004 estimates the serialized size of each #[contracttype] struct and enum and compares it against the configured ledger entry limit (default 64 kB, with an "approaching" threshold at 80%). It reports two levels:

  • ExceedsLimit — the estimated entry size is over the hard limit.
  • ApproachingLimit — the estimated size is within the configured fraction of the limit.

The limit and threshold are configurable via .sanctify.toml.

Why it matters

Soroban rejects a ledger entry write when the serialized value exceeds the network's size limit. Because the rejection happens at write time, a struct that grows over time (for example a Vec of holders or a Map keyed by user) will eventually cause mid-transaction failures that brick the affected code path — often only on mainnet, under real load, after audit.

Vulnerable example

#![no_std]
use soroban_sdk::{contracttype, Address, Map, String, Vec};

#[contracttype]
pub struct Registry {
    // S004: an unbounded list/map embedded in one entry grows past the limit.
    pub members: Vec<Address>,
    pub metadata: Map<Address, String>,
    pub audit_log: Vec<String>,
}

Safe example

#![no_std]
use soroban_sdk::{contracttype, Address, String};

// Split the data across per-key entries instead of one giant struct.
#[contracttype]
pub enum DataKey {
    Member(Address),       // one small entry per member
    Metadata(Address),     // one small entry per member's metadata
    MemberCount,           // a single counter, not the full list
}

#[contracttype]
pub struct MemberRecord {
    pub joined_ledger: u32,
    pub label: String,
}

CVSS-style risk rating

  • Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
  • Base score: 5.3
  • Rating: Medium

The dominant impact is availability: writes to an oversized entry fail, denying the affected operation. There is no direct confidentiality or integrity loss.

How to fix

  1. Reduce the size of the flagged #[contracttype] by removing or shrinking large fields.
  2. Split monolithic structures across multiple keyed entries (one entry per user/item) instead of one collection in a single entry.
  3. Store counters and indexes separately from bulk data.
  4. If the estimate is a false positive for your network, raise ledger_limit in .sanctify.toml.

Related rules

Related rules: S005, S003

References