Pool-solvency property tests (#33) and rent-aware TTL management (#35) - #89
Open
Spagero763 wants to merge 2 commits into
Open
Pool-solvency property tests (#33) and rent-aware TTL management (#35)#89Spagero763 wants to merge 2 commits into
Spagero763 wants to merge 2 commits into
Conversation
The Soroban workspace did not build on main, which blocked every contracts CI check (fmt, clippy, test, cost budget, wasm). A bad merge had dropped definitions while leaving their users in place: - ProposalStatus enum (Pending/Executed/Cancelled/Expired), referenced by Proposal.status and the approve/cancel flow. - Fifteen Error variants used across the share-vault, sweep, and governance code (MathOverflow, InvalidThreshold, BootstrapComplete, StaleEpoch, the Proposal* lifecycle errors, the Withdrawal*/Insufficient* vault errors, ...). - Nine Vaultquest#72 share-vault DataKey variants (VaultShares, ShareBalance, ...). - The `use soroban_sdk::xdr::ToXdr` import behind the signer-set and draw-seed hashing. All restored minimally, preserving every feature already on main (the commit/reveal raffle, threshold governance, the NAV share vault). Also fixed to get green: - proxy::propose_upgrade had drifted to 11 parameters, over Soroban's 10-arg limit. Restored the MigrationCheck struct the tests already pass to bundle plan_hash/state_hash/compatible back to 9 args. - execute_upgrade compared signer_epoch against an untyped storage read that inferred to (); annotated it u32. - Latent clippy findings that -D warnings rejects (needless u32 casts, a len()==0, an index-into-slice loop). - No Cargo.lock was committed, so soroban-env-host 21 resolved ed25519-dalek 3.0.0 whose CryptoRng bound ChaCha20Rng does not satisfy. Pinned to 2.x and committed the lockfile for reproducible builds. - Re-measured cost_thresholds.txt against the now-compiling contract; the old baseline predated the participant-registry and signer-set-hash work and could never be validated while the crate did not build. All 93 existing contract tests pass; fmt, clippy -D warnings, cost budget, and the wasm release build are green.
…anagement (Vaultquest#35) Vaultquest#33 — state-machine property tests and fuzzing for pool solvency. model.rs is an implementation-independent reference model of the pool's observable state and the outcome of every solvency entrypoint (no Env, storage, or auth). model_test.rs generates constrained command sequences across four actors and ledger time and replays each against both the model and the real contract, asserting after every step that they agree on accept/reject and return value, that a rejected call leaves state unchanged, and that the invariants hold on the contract's actual state: conservation (total_deposited equals the sum of current participants' principal), non-negative balances, claimable bounded by principal, multiplier within its tier, one-time withdrawal, and reentrancy lock released. proptest shrinks any failure to a minimal trace and prints the seed; PROPTEST_CASES raises the budget for nightly. Seeded traces cover repeated claim, lock expiry, one-time withdrawal, join-before-create, and arithmetic overflow — the last surfaced that deposit accounting used unchecked i128 addition, now guarded with checked_add returning MathOverflow (see the repair commit). Vaultquest#35 — rent-aware TTL management and verifiable state archival. ttl.rs is the pure decision layer: a KeyClass policy table with per-class minimum TTL, bounded extension targets clamped to a hard ceiling, and an approved-classes gate that blocks rent-exhaustion abuse; a checkpointed batch sweeper whose plan is a pure function of (total, cursor, budget) so a duplicated or retried sweep repeats work rather than skipping keys, with a staleness alert that fires before an active entry can expire; and a hash-chained archive (genesis/fold/verify/contains_at) whose root anyone can recompute to verify integrity and from which records can be reconstructed. Both modules are documented in docs/POOL_SOLVENCY_TESTS.md and docs/TTL_MANAGEMENT.md. 20 new tests (8 solvency + 12 TTL); the full contract suite is 113 tests, with fmt, clippy -D warnings, cost budget, and the wasm release build all green.
|
Maintainer review: this PR currently has merge conflicts with |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #33
Closes #35
Two contract tasks — pool-solvency property tests (#33) and rent-aware TTL management (#35) — plus the build repair both depend on.
First, a build repair (the "CLI issue")
main's Soroban workspace did not compile, so every contracts CI check (fmt, clippy, test, cost budget, wasm) was red. A bad merge had dropped definitions while leaving their users in place. The first commit restores them minimally, preserving every feature already on main (the commit/reveal raffle, threshold governance, the NAV share vault):ProposalStatusenum (referenced byProposal.status).Errorvariants used across the share-vault, sweep, and governance code (MathOverflow,InvalidThreshold,BootstrapComplete,StaleEpoch, theProposal*lifecycle errors, theWithdrawal*/Insufficient*vault errors, …).#72share-vaultDataKeyvariants.use soroban_sdk::xdr::ToXdrimport behind signer-set and draw-seed hashing.proxy::propose_upgradehad drifted to 11 parameters (over Soroban's 10-arg limit); restored theMigrationCheckstruct the tests already pass to bundle it back to 9.GovernanceEpochread that inferred to(), latent clippy findings that-D warningsrejects, and a missingCargo.lock(without it,soroban-env-host 21resolvesed25519-dalek 3.0.0, whoseCryptoRngboundChaCha20Rngdoesn't satisfy — pinned to 2.x).cost_thresholds.txt; the old baseline predated the participant-registry / signer-set-hash work and could never be validated while the crate didn't build.All 93 pre-existing contract tests pass after the repair.
#33 — state-machine property tests and fuzzing for pool solvency
model.rsis an implementation-independent reference model of the pool's observable state and the outcome of every solvency entrypoint — noEnv, no storage, no auth, so it is a genuine independent oracle.model_test.rsgenerates constrained command sequences across four actors and ledger time and replays each command against both the model and the real contract, asserting after every step:total_depositedequals the sum of current participants' principal, checked on-chain too), non-negative balances,claimable <= deposited, multiplier within its tier, one-time withdrawal, reentrancy lock released.proptest shrinks any failure to a minimal trace and prints the seed;
PROPTEST_CASESraises the budget for a nightly run. Seeded traces pin the required cases: repeated claim, lock expiry, one-time withdrawal, join-before-create, and arithmetic overflow.What it found:
depositaccounting used uncheckedi128addition (a panic/abort on overflow rather than a clean error). Now guarded withchecked_addreturningMathOverflow, so a deposit can never wrap a participant's principal or the pool total.Scope: the model covers the balance/solvency entrypoints (create, join, deposit, deposit_with_duration, claim, withdraw). The multisig-governance and raffle-draw state machines are their own machines with dedicated tests in
test.rs.#35 — rent-aware TTL management and verifiable state archival
ttl.rsis the pure decision layer a sweeper (on-chain or off-chain) drives:KeyClasspolicy table (ActiveCritical/Pending/Historical/Reconstructible) fixing each key's minimum TTL, bump target, and archive rule in one auditable place.decidereturnsSkip/Extend/Archivepurely from policy and remaining life; every extension is clamped to a hard ceiling, and only approved classes are auto-bumpable, so no untrusted key can draw rent.Extendis idempotent (extend_ttlonly raises TTL), so a crashed sweep is safe to re-run.plan_batchis entry-bounded and its plan is a pure function of(total, cursor, budget), so a duplicated or retried sweep repeats work rather than skipping keys; the cursor wraps for a perpetual self-resuming loop.is_sweep_staleis the alert that fires before an active entry can expire.genesis/fold/verify/contains_at); anyone can recompute the root to check integrity, and a restore tool replays records against the committed root to reconstruct.Documented in
docs/POOL_SOLVENCY_TESTS.mdanddocs/TTL_MANAGEMENT.md.Verification
20 new tests (8 solvency + 12 TTL); 113 total. The diff is 11 files and touches no
test_snapshots(those tracked files are left exactly as they are on main).