Cosmic Bull

Rendered from pearl/r/feesplit/FIXES.md at commit f191063fd89d in the project repository. The committed file is the source of truth; this page is a rendering of it.

fee_split — security fix series (2026-09-21)

Base: mechanical pearl port (port.py, now a neutered historical artifact) of SillyZir/fee_split @ 819239ad5ddc46cf685f5ff363cabb7290848c1f. The user authorized fixing the audit YELLOWs; the .gno files in this directory are port + fix series and are the workspace source of truth.

Deployment status — read this first. The v1 realm deployed at gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/fee_split (tx 061c89b1, h596803) is IMMUTABLE and retains the pre-fix shape (audited safe on all reachable paths — the fixes remove fragility, not an exploit). This fixed source can only ship as a NEW realm path (e.g. .../fee_split_v2); doing so requires updating the module path in gnomod.toml AND the hardcoded package path in the test fund() helper, and needs separate deploy authorization.

Round-1 audit findings → fixes

#FindingFixRegression test
Y1caller() helper derived identity via stack-walking unsafe.PreviousRealm() in a non-crossing helper; Deposit's payment guard and the Claim/ClaimFees send-source used the same walker family — correct on all current paths, enforced only by call-site disciplineAll 10 guarded entrypoints declare cur realm; identity is cur.Previous().Address() inline; payment guard is cur.Previous().IsUserCall(); sends originate from cur.Address(); helper deleted; unsafe retained only for OriginSend (×2) and init's OriginCallerwhole suite (verification audit traced semantic equivalence on all paths: direct EOA / realm-routed / MsgRun)
Y2Six test-coverage gaps around the exact guards the port had to preserveFour new tests: stray-send on the five unpinned functions; archived-split refusal of both value paths; two-coin envelope; equal-share dust tie (first-listed-wins). MsgRun-shape refusal is not constructible in the test driver (SetRealm accepts only user and /r/ realms) — documented at the code-realm test; the init feeAdmin capture is untestable in the test VM and was verified LIVE (GetFeeInfo admin == deployer)TestStraySendRejectedOnAllSplitFunctions, TestArchivedSplitRefusesDepositAndClaim, TestDeposit_TwoCoinEnvelopeRejected, TestDust_EqualShareTieGoesToFirst
Y3Deployment preconditions (operational, not code): unrestricted-ugnot network; fee-admin key custodyUnrestricted ugnot verified live before the v1 deploy (realm-address sends succeed on pearl-1); admin == deployer verified live post-deploy. OPEN ITEM: the deployed v1's fee admin is the hot agent key — nominating a user-controlled backup admin via the two-step handover needs an address from the user— (operational)

Verification-round finding → fix

#FindingFix
Y-NEW-1Stale port.py presented itself as the current pipeline and, if rerun as documented, would silently regenerate the pre-fix v1 shape over the fixed filesBoth apps' port.py scripts (here and r/timelock_guardian/) now sys.exit with a loud historical-artifact notice before touching anything

Suite: 59 tests, all passing on the chain/pearl toolchain (c4c72fd); lint clean; full workspace green. Verification audit (fresh context, diffed against the LIVE deployed v1 bytes): all fixes VERIFIED, no behavioral drift outside the authorized edit surface.

Provenance v2 (2026-09-21, post-push)

Remediation pushed upstream: SillyZir/fee_split @ e5aadfebc890c21ade4076e1d75c9c0e0dd77809 (main), authored solely by SillyZir, no AI attribution (verified via fresh clone + GitHub API). GitHub is again the source of truth; the transformation to this directory is T1 ONLY: module-path + PackageAddress namespace rewrite (gno.land/r/fee_split -> gno.land/r/g1ut6.../fee_split), verified byte-exact against the fresh clone.