Skip to content

feat: referral loop guard, merkle fuzz targets, TTL rent model, ABI snapshot CI - #1083

Merged
joelpeace48-cell merged 2 commits into
FinesseStudioLab:mainfrom
codemagician1949:feat/referral-loop-fuzz-rent-abi-743-799-803-805
Jul 29, 2026
Merged

feat: referral loop guard, merkle fuzz targets, TTL rent model, ABI snapshot CI#1083
joelpeace48-cell merged 2 commits into
FinesseStudioLab:mainfrom
codemagician1949:feat/referral-loop-fuzz-rent-abi-743-799-803-805

Conversation

@codemagician1949

Copy link
Copy Markdown
Contributor

Summary

  • Contracts: Referral self/loop prevention and sybil guard in campaign referrals #743 — Referral self/loop prevention and sybil guard: Added ReferralLoop (error 123) and a permanent REFERRAL_LOCK storage key. do_register now rejects direct cycles (A→B when B's lock already points to A). The lock is written on first registration and survives deregister, so a participant can't swap referrers or farm REFERRAL_COUNT via de/re-register cycles. REFERRAL_COUNT is only ever incremented once per participant, guarded by an already_attributed check. Three new unit tests cover self-referral (existing), direct loops, count inflation, and referrer-swap attempts.

  • Testing: Expand fuzzing for merkle proofs, XDR decoding, and webhook payloads #803 — Expanded fuzzing for merkle proof verification: Two new proptest targets in fuzz_test.rs (fuzz_merkle_random_leaf_rejected — 200 cases, fuzz_merkle_bit_flip_in_proof_rejected — 100 cases). Both generate random leaf/proof bytes against a fixed non-zero root and assert Error::NotInAllowlist — verifying the on-chain gate cannot be bypassed with garbage input. These join the existing CI fuzz run (cargo test -- fuzz_).

  • Performance: Contract storage rent / TTL budgeting model and alerts #799 — Storage rent / TTL budgeting model: Added docs/TTL_RENT_MODEL.md with the full rent cost formula, per-entry cost table (1K–1M participants), extension strategy (bump-on-write, sweeper, pruning), and a recommended CI constant check. Added scripts/check-ttl-rent.js — reads storage_stats from a live contract and prints ALERT for entries within the configurable threshold (RENT_ALERT_THRESHOLD, default 10,000 ledgers ≈ 0.7 days); exits non-zero for use in cron monitoring.

  • Release: ABI / contract-interface snapshot tests to catch breaking spec changes #805 — ABI / contract-interface snapshot tests: Added contracts/campaign/contract_spec.json pinning all 30 public functions and all 24 error codes (including the new ReferralLoop = 123). Added a CI step to contracts-ci.yml that verifies the snapshot is present and that error codes are gap-free (100–123); any interface change must update the snapshot and bump schema_version or the build fails.

Test plan

  • cargo test -p trivela-campaign-contract test_referral_direct_loop_rejected — passes with ReferralLoop error returned
  • cargo test -p trivela-campaign-contract test_referral_count_not_inflated_by_re_register — count stays at 1 after cycle
  • cargo test -p trivela-campaign-contract test_referral_lock_prevents_referrer_swap_on_re_register — referrer_b count stays 0
  • cargo test -p trivela-campaign-contract -- fuzz_merkle_ — both fuzz targets run 200/100 cases with no panics
  • node scripts/check-ttl-rent.js --network testnet --contract <ID> — prints estimation table and exits 0 when no live contract available
  • CI Verify campaign contract ABI snapshot step passes with the committed spec

Closes #743
Closes #799
Closes #803
Closes #805

…esseStudioLab#743 FinesseStudioLab#799 FinesseStudioLab#803 FinesseStudioLab#805)

- FinesseStudioLab#743: Add ReferralLoop (error 123) and REFERRAL_LOCK storage key to campaign
  contract. do_register now rejects direct referral cycles (A→B where B's lock
  already points to A) with Error::ReferralLoop. REFERRAL_LOCK is written on
  first registration and persists through deregister, so re-registering with a
  different referrer is a no-op (sybil guard). REFERRAL_COUNT is only incremented
  once per participant per referrer — already_attributed check prevents farming
  via de/re-register. Three new unit tests cover all abuse paths.

- FinesseStudioLab#803: Add two proptest fuzz targets to fuzz_test.rs (fuzz_merkle_random_leaf_
  rejected, fuzz_merkle_bit_flip_in_proof_rejected). Each generates random leaf /
  proof bytes against a fixed non-zero Merkle root and asserts Error::NotInAllowlist
  is returned — verifying the allowlist gate cannot be bypassed with garbage input.

- FinesseStudioLab#799: Add docs/TTL_RENT_MODEL.md documenting the rent cost formula, per-entry
  cost table, extension strategy, and budget projections. Add scripts/check-ttl-
  rent.js — reads storage_stats from a live contract and prints ALERT for entries
  within RENT_ALERT_THRESHOLD ledgers of expiry (default 10,000 / ~0.7 days);
  exits non-zero when alerts are present for use in cron monitoring.

- FinesseStudioLab#805: Add contracts/campaign/contract_spec.json — pinned ABI snapshot listing
  all 30 functions and all 24 error codes. Add CI step in contracts-ci.yml to
  verify the snapshot is present and error codes are gap-free; any interface
  change must update the snapshot and bump schema_version or the build fails.

Closes FinesseStudioLab#743
Closes FinesseStudioLab#799
Closes FinesseStudioLab#803
Closes FinesseStudioLab#805
Comment thread scripts/check-ttl-rent.js
`--fn ${fn}`,
args,
].filter(Boolean).join(' ');
const output = execSync(cmd, { encoding: 'utf8', timeout: 15_000 });
@joelpeace48-cell
joelpeace48-cell merged commit e167895 into FinesseStudioLab:main Jul 29, 2026
3 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants