persistence pool
version 0.1 · updated 2026-04-16 · status: published
scope
This document defines the Persistence Pool: a Solidity contract on Base that holds cUSDC and compensates provider nodes for audited replication. It specifies the contract interface, the challenge-response protocol, the compensation formula, and the parameters governable via Council (RFC-7). Provider nodes MUST implement valid responses to challenges per §3 to be eligible for payment.
MUST, SHOULD, MAY follow RFC 2119.
contract interface
The canonical Persistence Pool interface includes, at a minimum:
interface IPersistencePool {
// A provider node registers with region and replication intent.
function register(uint8 region) external;
// The contract emits a byte-range challenge for a CID under custody.
event Challenge(
bytes32 indexed challengeId,
address indexed provider,
bytes32 cidHash,
uint64 rangeStart,
uint64 rangeEnd,
uint64 deadlineBlock
);
// Provider responds with the requested bytes + Merkle proof.
function respond(
bytes32 challengeId,
bytes calldata rangeBytes,
bytes32[] calldata merkleProof
) external;
// Epoch closes, disbursement computed off-chain, submitted in batch.
function submitSettlement(
uint64 epoch,
bytes32 merkleRoot,
address[] calldata providers,
uint256[] calldata amounts
) external;
}Reference implementations live in packages/contracts/src/PersistencePool.sol. The canonical address on Base Sepolia is published in the network footer.
challenge-response protocol
At random intervals (Poisson with rate λ per node per epoch), the contract emits a challenge consisting of:
- challengeId — unique identifier;
- cidHash — hash of the target CID under the provider’s custody;
- [rangeStart, rangeEnd] — random byte range within the object;
- deadlineBlock — block number by which the response must be submitted.
Provider nodes MUST, within the deadline:
- read the bytes O[rangeStart..rangeEnd] from locally stored data;
- compute the Merkle proof of the range against the pre-computed root for the CID (64 KiB chunk tree);
- submit via respond() the bytes and the proof.
The contract verifies the proof; a valid response increments R_i for the provider. A missing or invalid response decrements it. The deadline window SHOULD be short enough (typically ≤ 2 minutes) to defeat inter-peer fetch at challenge time.
compensation formula
The compensation of a provider node in epoch t is:
P_i(t) = R_i(t) · B_i(t) · W_region(i) · ρ(t)
- R_i(t) ∈ [0,1] — fraction of challenges correctly answered in the epoch.
- B_i(t) — byte-hours of audited replicated content (sum of object sizes under custody × epoch hours).
- W_region(i) ∈ {0.5, 1.0, 1.5} — regional weight (§5).
- ρ(t) — pool unit rate for the epoch: ε · S(t) / Σ_i (R_i · B_i · W_region), where S(t) is the pool balance and ε is the per-epoch disbursement fraction.
By construction, Σ_i P_i(t) = ε · S(t). The contract MUST reject settlements that violate this conservation.
region weights
Regional weights encode geographic scarcity of custody. Initial values:
| region | weight | rationale |
|---|---|---|
| 0 (default) | 1.0 | global north — baseline |
| 1 (low scarcity) | 0.5 | regions with >30% of nodes — weighted less |
| 2 (high scarcity) | 1.5 | global south, central asia, africa — weighted more |
Regional classification is re-evaluated every 6 epochs by the Council, based on a public node distribution map. Changes MUST be announced on the Trust Ledger with ≥ 14 days of notice.
epochs and disbursement
- default epoch duration: 168 hours (7 days).
- default disbursement fraction ε: 0.10 (10% of balance per epoch).
- default challenge rate λ: 100 challenges per node per epoch — sufficient for a dishonest provider’s survival probability to be (1 − p)^λ ≈ 10^-100 for p = 0.9.
- settlement is computed off-chain by a trusted aggregator (currently Aevia LLC), producing a Merkle root of (provider → amount); the contract verifies conservation and executes payments.
Parameters ε, λ, and epoch duration are governable via Council (RFC-7) with a veto process.
security considerations
- dishonest provider: defeated by the combination of random byte-range + short deadline (§3). Survival probability made explicit in §10(a) of the whitepaper.
- Sybil: neutralized because payment is proportional to B_i actually replicated, not node count.
- aggregator capture: a malicious aggregator could submit wrong settlements. Mitigation: settlements MUST have an on-chain contestation window (e.g., 72h after submission) during which any provider can submit a counter-proof. Migration to decentralized aggregation is in RFC-7 scope.
- economic attack via B dumping: a large actor could inflate B, depressing ρ for small operators. The Council MAY propose a contract fork excluding the actor.
references
- IETF RFC 2119 — Key words for RFCs
- Aevia Whitepaper §5, §10, §12
- RFC-2 — Content Addressing
- RFC-6 — Risk Score (draft)
- RFC-7 — Moderation and Ecumenical Jury (draft)
- cUSDC on Base — Circle documentation
- PersistencePool.sol — reference implementation