Docs/UX: L-02 ReferralRegistry registration ordering (first included tx wins; mitigated by 1 CL8Y burn) #121
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#121
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Source
audits/audit_smartcontract_1777813071.md— L-02: Referral code registration is front-runnableSummary
ReferralRegistry.registerCode(string)emits the plaintext code in calldata. Any observer who sees a pending registration transaction can submit the same normalized code with a higher gas price (or otherwise get earlier inclusion in the same block). The first transaction that successfully executes wins: subsequent attemptsrevertwithReferralRegistry: code taken. The intended registrant loses the race but does not pay the burn on the failed tx; the successful squatter paysregistrationBurnAmountCL8Y (sent to the dead burn address).Product decision for this issue: Treat ordering as transparent and mempool-fair: the first included successful registration wins. Do not implement commit-reveal or offchain reservations in this work item. Mitigation already in protocol: each successful registration requires a fixed CL8Y burn (see
DeployDev.s.sol—1e18wei = 1 CL8Y at 18 decimals; tests use the same pattern inTimeCurveReferral.t.sol), which raises the cost of purely griefing squatting and makes casual front-running economically explicit.Technical detail
contracts/src/ReferralRegistry.sol—registerCode,codeOwner,ownerCodebytes32 codeHash→ one owner; one owner → one code (IReferralRegistry)cl8yToken.safeTransferFrom(msg.sender, BURN_ADDRESS, registrationBurnAmount)after uniqueness checksregisterCodewith identical normalized stringRecommended fix (documentation + UX)
/referrals/ register panel (ReferralRegisterSection.tsx), add short, non-alarmist copy: e.g. desirable codes may be claimed by others who see the same pending tx; users accept onchain ordering and the published burn cost.ReferralRegistry.sol, extend@noticeonregisterCodeto reference first successful inclusion and calldata visibility (keeps expectations next to the implementation; no bytecode behavior change if only comments).Out of scope here (future issues if ever required): commit-reveal registration, signed reservations from an admin, private mempools / Flashbots-only registration flows.
Files to update (checklist)
Documentation (required)
docs/product/referrals.mddocs/testing/invariants-and-business-logic.mdFrontend (required)
frontend/src/pages/ReferralsPage.tsxfrontend/src/pages/referrals/ReferralRegisterSection.tsxContracts (optional comment-only)
contracts/src/ReferralRegistry.solregisterCode— first-included wins; calldata visible; burn mitigates spamAudit trail (optional)
audits/audit_smartcontract_1777813071.mdManual QA (recommended)
docs/testing/manual-qa-checklists.mddocs/product/referrals.mdNo change expected (unless copy references added)
contracts/src/TimeCurve.sol— referral apply path unchangedskills/README.md/ agent skills — only if playbooks mention “guaranteed” code reservationRegression tests
Behavior is unchanged — this is primarily a documentation and disclosure item. Recommended verification:
cd contracts && FOUNDRY_PROFILE=ci forge test(referral tests inTimeCurveReferral.t.sol, registry deploy paths).npm test/ Vitest for any touched strings-only components (if tests assert copy, update snapshots).frontend/e2e/anvil-referrals.spec.ts— only extend if adding a stabledata-testidfor the disclosure line (optional).Optional future test (separate issue): If a commit-reveal design is adopted, add dedicated Foundry tests for the two-phase flow.
Acceptance criteria
docs/product/referrals.mdexplicitly states: first successful onchain registration owns the code; public mempool can reorder competingregisterCodetxs; squatting is limited byregistrationBurnAmountCL8Y burn to the winner only on success.registerCodelogic unless product later requests commit-reveal (out of scope).Verification checklist (multi-step)
A. Doc accuracy
docs/product/referrals.mdand confirm the new subsection matchesReferralRegistrysemantics (code taken,already registered, burn timing).1e18inDeployDev.s.soland product line “1 CL8Y” in existing doc.B. Frontend
/referralswith registry configured.registrationBurnAmount()display still matches chain (no regression).C. CI / tests
forge test(CI profile) passes.D. Sign-off
Non-goals
Keywords:
ReferralRegistry,registerCode, front-running, mempool, L-02, CL8Y burn, documentation, UX disclosurementioned in commit
edce84ca3cmentioned in commit
9905b25c9cImplemented on
main(commits through9905b25) — referralregisterCodeordering / mempool fairness per issue spec (audit L‑02 mitigation via docs + UX; no bytecode behavior change aside from ReferralRegistry NatSpec).cc @brouie — leaving this issue open for your sign-off. Please verify when you have a cycle.
What changed (short)
INV-REFERRAL-121-UX/ §121, strategy § Stage 1 (deterministic mempool tests out of scope; E2E asserts disclosure element).ReferralRegisterSection.tsx—data-testid="referrals-register-ordering-disclosure"before Register & burn CL8Y; overview strip onReferralsPage.tsx.ReferralRegistry.solregisterCodeNatSpec (first-successful inclusion, calldata visibility, burn-after-checks).skills/README.md, contributor.cursor/skills/yieldomega-guardrailsitem 15.Verification checklist for @brouie
registerCode; failures do not burn; public mempool wording).referrals: Unregistered + connected wallet shows disclosure above the register CTA; layout OK on narrow width; burn line still fromregistrationBurnAmount().bash scripts/e2e-anvil.sh—anvil-referrals.spec.tsexpectsreferrals-register-ordering-disclosurevisible before register (same mock wallet caveat as existing spec if wallet already registered).FOUNDRY_PROFILE=ci forge test;frontendVitest unchanged/green.verified on commit
edce84c(merged via9905b25). disclosure lands in all 3 surfaces from your spec.inline form disclosure in
ReferralRegisterSection.tsx(testidreferrals-register-ordering-disclosure):page-level disclosure in
ReferralsPage.tsx:doc-level disclosure in
docs/product/referrals.mdcovers the mempool calldata risk, the burn-as-economic-barrier-not-FIFO model, and the v1 product stance (transparent ordering, no commit-reveal).audit
L-02cross-link added to the audit MD per your spec footnote.E2E test
frontend/e2e/anvil-referrals.spec.tsupdated to assert disclosure visibility per the diff stat. v1 framing preserved — no commit-reveal, registration as transparent on-chain auction with the 1 CL8Y burn as the spam barrier.