Security review (post-audit, pre-deploy): two findings on the new presale CHARM weight code #126
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#126
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?
spent the QA window today doing a security pass on the audit
audit_smartcontract_1777813071.md+ the new code you just pushed (IDoubPresaleBeneficiary.sol,TimecurvePresaleCharmHeaderBadge.tsx, indexer migrationtimecurve_presale_vesting_set). two findings worth flagging before tonight's deploy.Finding 1 — TimeCurve.setDoubPresaleVesting admin swap, no sale-state guard
TimeCurve.sol:303-306:setter is
onlyOwnerwith no sale-state check. owner can swapdoubPresaleVestingto a malicious view contract DURING an active sale that returnsisBeneficiary(ownerControlledAddress) == true. that owner-controlled address then gets +15% CHARM weight on every subsequent buy.squarely in H-01 territory from your audit (privileged role can alter core economics without onchain delay) — but it's a NEW post-audit setter so worth surfacing explicitly. mitigations:
saleStart == 0so it can't be swapped after sale opensreentrancy is fine —
buy()isnonReentrantso the external view call toisBeneficiarycan't recurse.Finding 2 — TimecurvePresaleCharmHeaderBadge hardcodes the 15%
frontend/src/layout/TimecurvePresaleCharmHeaderBadge.tsxline 28:the percentage is hardcoded text. if
PRESALE_CHARM_WEIGHT_BPSever changes onchain the badge silently lies. same anti-pattern as #110 (FeeTransparency hardcodes 18 decimals) which is already open and you've marked low-pri.low-pri / pre-launch hardening — either label from a contract read of the BPS constant, or accept the hardcode and document.
Other audit findings status
H-01 + M-03 + L-01 + L-03 are still unfiled from your audit. happy to file what's worth tracking if you want me to — otherwise leaving them for your triage tonight.
third finding from continued review of
audits/audit_smartcontract_1777813071.mdinvariant section.Finding 3 — RabbitTreasury deposit/withdraw missing nonReentrant
your own audit flags this in the residual concerns under RabbitTreasury ("
withdrawis notnonReentrant; it appears safe for standard ERC20 but should not be paired with malicious hook-like reserve assets"). confirmed at source —RabbitTreasury.soldeposit (line 346) and withdraw (line 366) are bothwhenNotPausedonly, no reentrancy guard.current safety relies entirely on L-05's standard-ERC20 deployment covenant holding forever. adding
nonReentrantis a 1-line defense-in-depth that closes the residual concern without affecting any flow. costs ~2.4k gas per call, breaks nothing.if multi-asset support ever lands per L-05's recommendation ("For future multi-asset support, measure balance deltas or isolate adapters per asset type"), this becomes load-bearing.
@PlasticDigits — pre-launch hardening, your call whether to add now or post-launch.
Governanve has to be trusted at this point in time.
Hardcoded +15% is fine for 1 sale as it is verifiable
RabbitTreasury is not part of this deployment release.
Marking low for future review & implementation
fourth finding from continued security review pass.
Finding 4 — RabbitTreasury.withdraw CEI ordering bug enables cooldown bypass on hook-bearing assets
RabbitTreasury.sol:393-398:lastWithdrawEpochIdis the cooldown gate state. it's written AFTERsafeTransfer. on a hook-bearing reserve asset (ERC777, callback ERC20, future Yieldomega asset), receiver can re-enterwithdrawbefore the cooldown timestamp updates. multiple withdraws in a single epoch.your audit's residual concern called this out generically ("
withdrawis notnonReentrant; appears safe for standard ERC20 but should not be paired with malicious hook-like reserve assets") — this is the specific consequence: not a fund drain, but a cooldown rate-limit-bypass primitive. since cooldown is the only thing protecting against same-epoch repeat redemption, bypass = effective cooldown disablement on hook assets.fix is 2 lines: move the
lastWithdrawEpochId+cumulativeWithdrawFeeswrites BEFORE thesafeTransfer. or addnonReentrantmodifier. either makes the cooldown invariant load-bearing instead of covenant-dependent.per your earlier reply, RabbitTreasury isn't in tonight's deployment release — flagging for the post-launch RabbitTreasury hardening pass.
mentioned in issue #127
mentioned in issue #128
mentioned in issue #129
mentioned in issue #130
mentioned in issue #131
mentioned in issue #138
mentioned in issue #164