Protocol
No comments in final Solidity. Production / deployable contracts under packages/contracts (and anything verified on-chain) must ship with zero //, ///, or /* */ comments — including NatSpec. Behavior and invariants live in this doc, Foundry tests, and off-chain docs only.
docs/contracts/*.sol may keep brief comments as a readable reference while the product is specified.packages/contracts for build, deploy, or explorer verification: strip all comments.pragma stay; do not use comment blocks as documentation on-chain.FORGE does not replace PONS token-launch contracts in MVP. FORGE adds only contracts needed for transparent platform economics and later utility.
MVP contracts:
AgentFeeVaultAgentFeeVaultFactoryForgeLaunchRouter — atomic vault create + PONS launch in one user transactionPhase 1.1:
ForgeBoostBurner (optional dedicated burn/boost proof contract)Creators must not sign two separate transactions (vault deploy, then PONS launch). MVP ships a ForgeLaunchRouter that, in a single msg.sender call from the creator wallet:
AgentFeeVaultFactory.createVault(agentId, beneficiary) (CREATE2)launchToken / launchAndBuy with creatorFeeRecipient = vaultInitiator / salt namespace: The router must preserve PONS’s initiating-wallet semantics the same way the official launch-and-buy router does (trusted-forwarder / launchTokenFor-style path). Salt namespace, deployer attribution, and predictLaunchAddresses must use the creator wallet, not the router address. If PONS only allows that pattern through its published router interface, wrap it; do not invent a path that makes the router the deployer.
ECA (Expected Contract Address) simulate — required UX before Launch:
Before the user clicks Launch, a Compute / Simulate addresses action (no wallet signature) must return and display:
| Address | Source |
|---|---|
| Vault ECA | AgentFeeVaultFactory.predictVault(agentId, owner, beneficiary) — owner is the launching creator wallet |
| Token ECA | PONS predictLaunchAddresses(...) with pinned salt + params |
| Curve ECA | same PONS predict call |
Also pin and show: salt, expectedEconomics (from previewLaunchEconomics), launch fee, pair asset, vault beneficiary, and current fee disclosure (live platformFeeBps + callerTipBps — default 15% of gross to platform, then 1% of the beneficiary pool to the claim caller).
Launch-intent then builds one unsigned tx to ForgeLaunchRouter using those pinned values. Re-simulate if beneficiary, salt, launch config, or pair token changes. Intent expires; stale economics must force a fresh simulate.
Purpose: be the PONS creatorFeeRecipient, claim creator proceeds from the PONS fee escrow and split claimed assets between FORGE, the permissionless claim caller, and the Agent beneficiary.
Tip is not taken from the platform cut. Order:
platformAmount = gross * platformFeeBps / 10_000 // default 15% of gross (untouched)
beneficiaryPool = gross - platformAmount // default 85% of gross
callerAmount = beneficiaryPool * callerTipBps / 10_000 // default 1% of beneficiary pool
beneficiaryAmount = beneficiaryPool - callerAmount // default 99% of beneficiary pool| Party | Basis | Default |
|---|---|---|
| Platform (FORGE) | % of gross | 1500 bps = 15% of gross |
| Claim caller | % of beneficiary pool (after platform) | 100 bps = 1% of beneficiary share |
| Beneficiary | remainder of beneficiary pool | 99% of beneficiary share (~84.15% of gross at defaults) |
Platform always receives its full BPS of gross. The 1% tip comes only from what would otherwise go to the beneficiary.
claimAndSplitNative / claimAndSplitToken (and the split-only helpers).callerTipBps of the post-platform beneficiary pool (default 1%) in the same asset.msg.sender in the claim/split transaction.FORGE runs its own keeper in apps/worker that evaluates every vault and only submits a claim tx when the caller tip covers estimated gas + configured profit. Public bots may still claim anytime. Full rules: Fee keeper.
platformFeeBps and callerTipBps live on AgentFeeVaultFactory, mutable by factory admin (setPlatformFeeBps, setCallerTipBps).MAX_PLATFORM_FEE_BPS = 3000 (30% of gross), MAX_CALLER_TIP_BPS = 500 (5% of beneficiary pool). Independent — tip does not reduce platform.setPlatformRecipient admin-only. Prefer multisig admin before real value./config/public must show live BPS values and state that tip is from beneficiary share, not platform.Properties:
owner via setBeneficiary (migrate wallets / action contracts post-launch)transferOwnership (e.g. to a multisig)agentId only (one vault per agent); constructor includes owner + initial beneficiarynonReentrantBeneficiaryUpdated / OwnershipTransferred and detailed split events| Parameter | Who | Why |
|---|---|---|
| Vault beneficiary | Vault owner (creator) | Migrate agent wallet / action contract without new vault |
| Vault ownership | Vault owner | Hand control to multisig / new ops key |
| Platform BPS / caller tip / platform recipient | Factory admin | Platform economics |
| Beneficiary by factory admin | Forbidden | Creators must not have fees redirected by FORGE |
Disclose on fee transparency: current beneficiary, vault owner, and that owner can update beneficiary on-chain. Index BeneficiaryUpdated so the UI stays current.
UI/API: authenticated creator (matching vault owner) gets unsigned setBeneficiary / transferOwnership txs from My Agents settings.
The beneficiary share (post-platform pool minus caller tip) may be:
Owner may point beneficiary at a new address after launch. FORGE does not make downstream action guarantees. The UI clearly displays current beneficiary, whether it is a contract, and vault owner.
For Phase 1.1, prefer an event-emitting contract over sending to an arbitrary dead address if you want strong campaign attribution:
burnForBoost(agentId, amount, packageId)Contract should transfer/burn FORGE and emit:
BoostBurned(address payer, bytes32 indexed agentId, uint256 amount, uint8 packageId)Backend only enables a campaign after event confirmation and price-package validation based on the server's quote policy.
MAX_PLATFORM_FEE_BPS or tip above MAX_CALLER_TIP_BPSsetBeneficiary / transferOwnershipmsg.sender of the claim/split and is carved only from the beneficiary poolInvariant examples:
Platform fee = platformFeeBps of vault gross. Claim caller tip = callerTipBps of the post-platform beneficiary pool (not of gross, not of platform). UI must say this clearly and refresh when admin changes BPS.
Admin APIs: POST /admin/fees/platform-bps, POST /admin/fees/caller-tip-bps. Chain is source of truth for splits. Keeper policy: Fee keeper.