Contracts: single-tx CHARM buy with ETH/USDM via configurable router (Kumbaya → TimeCurve buy) #65
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#65
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?
Summary
Expose an onchain entry path so participants can buy CHARM with native ETH or USDM in a single transaction, with the contract (or an approved router module) performing the Kumbaya swap leg + TimeCurve
buyatomically. Today the sale’s accepted asset is CL8Y-centric and the app composes separate user txs (wrap/approve/swap then CL8Y approve/buy).Motivation
charmWad” can be enforced in one atomic execution instead of relying on the wallet to complete a multi-step flow.Proposed direction (high level)
Configurable router / module address on
TimeCurve(or a dedicatedTimeCurveBuyRoutertrusted byTimeCurve) that:buy/buy(..., referral)with the resulting CL8Y spend so the user receives CHARM in the same tx.“Data from the frontend” in the sense of user-chosen route + limits (path, min/max input, deadline,
charmWador CL8Y spend target) supplied as opaque but validated calldata to the router—same information the frontend already derives for Kumbaya + TimeCurve, but signed once against a single contract entrypoint.Safety / invariants (must be explicit in spec):
TimeCurve.TimeCurvereads (seedocs/integrations/kumbaya.md, GitLab #46).Out of scope / follow-ups
exactOutputvsexactInputswap style) should be decided with reference to current frontend swap stack (frontend/src/lib/timeCurveKumbayaSwap.ts, sale session / arena models).References
docs/integrations/kumbaya.mdmentioned in commit
d36cccb6deImplemented (merged to
main)Single-transaction ETH or USDM (configured stable) → Kumbaya
exactOutput→ TimeCurve purchase:TimeCurve.buyFor(buyer, charmWad[, codeHash])— only callable bytimeCurveBuyRouter(zero = disabled). CL8Y is pulled from the router; all CHARM weight, WarBow, cooldown, and referral semantics usebuyer(same as a normalbuyfor that wallet).TimeCurveBuyRouter(immutable companion):buyViaKumbayarecomputes gross CL8Y fromcurrentPricePerCharmWad×charmWad, validates v3 packed path (CL8Y first, WETH or stable last), runsexactOutput, approves TimeCurve, callsbuyFor(msg.sender, …).PAY_ETH/PAY_STABLE(see contract constants).DeployKumbayaAnvilFixturesdeploys the buy router and callssetTimeCurveBuyRouter.AnvilKumbayaRouter: multi-hopquoteExactOutput/ first pass ofexactOutputnow walk hops from the CL8Y (output) end toward the spend token so two-hop USDM quotes match execution (fixes local fixture consistency).Docs / cross-links:
docs/integrations/kumbaya.md,docs/testing/invariants-and-business-logic.md,docs/testing/local-swap-testing.md,skills/README.md,.cursor/skills/yieldomega-guardrails/SKILL.md.@brouie please verify when you can. Checklist:
cd contracts && FOUNDRY_PROFILE=ci forge test— expect 188 tests green (includesTimeCurveBuyRouter.t.sol+buyFortests).cast calltimeCurveBuyRouter()on the TimeCurve proxy returns that address.quoteExactOutputfor CL8Y←WETH←USDM is in the same ballpark as before for single-step sanity; full path quote no longer underestimates input vsexactOutput(regression guard for fixture).setTimeCurveBuyRouter(address(0))to disablebuyFor; unauthorizedbuyForstill revertsTimeCurve: not buy router.buildV3PathExactOutputinkumbayaRoutes.tsbefore encouraging users to callbuyViaKumbaya.Issue left open per maintainer request.
mentioned in issue #66
mentioned in issue #67
mentioned in issue #72
mentioned in issue #78
@PlasticDigits source + selective live verification on the implementation merged to main.
Tests
cd contracts && FOUNDRY_PROFILE=ci forge test --match-contract TimeCurveBuyRouterTest:
cd contracts && FOUNDRY_PROFILE=ci forge test:
Source review
Contract gate (TimeCurve.sol):
Fixture quoter (AnvilKumbayaFixture.sol):
Live verification (default stack with timeCurveBuyRouter unset)
cast call 0x59b670e9fA9D0A427751Af201D676719a970857b 'timeCurveBuyRouter()(address)' returns 0x0 — proxy responds, default disabled state confirmed.
cast call 0x59b670e9fA9D0A427751Af201D676719a970857b 'buyFor(address,uint256,bool)' 0xc46b15f4B56489a16F561c22D5F0BA8bdCa80650 1000000000000000000 false reverts with: 'TimeCurve: not buy router' — exact match for AC4.
Same revert on the bytes32-codehash 4-arg variant.
Live items deferred to #78
scripts/start-local-anvil-stack.sh and contracts/script/anvil_rich_state.sh don't run DeployKumbayaAnvilFixtures — so the router-set state, USDM two-hop live quote, and full buyViaKumbaya tx receipt evidence need a separate fixtures deploy. Tracked at #78. AC5 (MegaETH/prod SwapRouter02 wire-up) is mainnet readiness, out of scope for local QA.
Closing #65. Live walkthrough proceeds via #78.
mentioned in commit
54e6ad92b4mentioned in issue #83
mentioned in issue #100
mentioned in issue #118
mentioned in issue #207
mentioned in issue #232