You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The partner agreement fixes the client's rate against a reference: the Coinbase EURC-USD reference minus 12.5 bps, and never worse than 15 bps below it. The forwarder's flat feeBps skim on whatever the DEX returns cannot express that. The contracts from #1272 are not deployed yet, so this changes the design before launch with no clone migration.
Decisions are recorded in the dated amendment to docs/adr-0005-monerium-b2b-onramp.md; behaviour in docs/architecture-monerium-b2b-onramp.md ("Fees, reference rate and subsidy").
What changes
Contracts (contracts/monerium-forwarder)
Fee policy in ppm per clone (targetPpm 1250, floorPpm 1500 at launch) behind the existing 24 h increase timelock; MAX_FEE_PPM caps both.
swapAndForward(referenceRate, routeIndex): the caller supplies the reference, the contract bounds it to MAX_REFERENCE_DEVIATION_BPS around Chainlink; permissionless callers get Chainlink and no subsidy.
Three bands: surplus above the target is the fee (capped), between floor and target passes through, below the floor is topped up from the vault.
New shared VortexSubsidyVault: treasury-funded, pays only factory clones to their fixed destination, per-swap cap and UTC-daily budget, pausable, withdraws only to the treasury. A vault that cannot cover reverts the whole swap.
SLIPPAGE_BPS (now 40 bps) is enforced on the client's net after fee and subsidy; the router minimum is zero and the post-condition is the guard.
Factory route whitelist validated on chain (EURe/EURC/USDC only, four Uniswap tiers, at most two hops, immutable router); routes are disabled, never removed.
Sweep delay fixtures to 7 days (P3); manifest scripts learn the fee policy, vault and routes (manifest v3).
Migration 079: executions carry reference (rate, source, trade id, time), route and subsidy; net is usdcOut - fee + subsidy.
reference-rate.ts computes a five-minute volume-weighted average of Coinbase Exchange EURC-USD one-minute candles before each swap (widened to an hour when the five minutes carry no volume), so a single thin weekend print cannot set the reference; the window is recorded on the execution row. The executor quotes every whitelisted route on the mainnet quoter, mirrors the contract settlement (projectSwap) and defers rather than sending when the vault could not cover, the net would breach the floor, the reference is unavailable or out of band, or no route quotes.
Crash recovery rebuilds the exact calldata from the persisted reference and route.
Monitoring: depth check over every route, subsidy-vault runway monitor, sweep-imminent note on stranding alerts.
Webhooks and the deposits endpoint expose an execution pricing block (reference, fee, subsidy) on each conversion.
Docs
ADR-0005 amendment and registry rows (B1, P1, P2, P3, P10, P11, new P12/P13), architecture, runbook (vault operations, triage rows, fork exercise), rollout terms inputs, security spec, API pages, OpenAPI.
Reaffirmed decisions: no payment bouncing, no guardian-triggered sweep to the fallback, permissionless path after 24 h accepted as unsubsidized.
Verification
forge test: 65 tests (unit, vault, invariants incl. pricing bounds and vault conservation). The mainnet fork suite compiles but was not run (no ETH_RPC_URL locally).
bun test on the B2B surface: 251 tests across 20 files against the Docker test database; API type-check, Biome, bun docs:api:check clean.
Reviewer notes
The old Sepolia manifest in contracts/monerium-forwarder/manifests/ is v2 and will fail verify-manifest until the contracts are redeployed; expected.
Still open before a deployment (rollout ledger): the 100 bps reference band value, whether the agreement's "Coinbase EURC oracle" means the Exchange ticker the keeper reads, and vault funding.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The partner agreement fixes the client's rate against a reference: the Coinbase EURC-USD reference minus 12.5 bps, and never worse than 15 bps below it. The forwarder's flat
feeBpsskim on whatever the DEX returns cannot express that. The contracts from #1272 are not deployed yet, so this changes the design before launch with no clone migration.Decisions are recorded in the dated amendment to
docs/adr-0005-monerium-b2b-onramp.md; behaviour indocs/architecture-monerium-b2b-onramp.md("Fees, reference rate and subsidy").What changes
Contracts (
contracts/monerium-forwarder)targetPpm1250,floorPpm1500 at launch) behind the existing 24 h increase timelock;MAX_FEE_PPMcaps both.swapAndForward(referenceRate, routeIndex): the caller supplies the reference, the contract bounds it toMAX_REFERENCE_DEVIATION_BPSaround Chainlink; permissionless callers get Chainlink and no subsidy.VortexSubsidyVault: treasury-funded, pays only factory clones to their fixed destination, per-swap cap and UTC-daily budget, pausable, withdraws only to the treasury. A vault that cannot cover reverts the whole swap.SLIPPAGE_BPS(now 40 bps) is enforced on the client's net after fee and subsidy; the router minimum is zero and the post-condition is the guard.Backend (
apps/api)monerium_accounts.fee_bpsbecomestarget_ppm/floor_ppm; provisioning, admin and read APIs, drift monitor follow.usdcOut - fee + subsidy.reference-rate.tscomputes a five-minute volume-weighted average of Coinbase Exchange EURC-USD one-minute candles before each swap (widened to an hour when the five minutes carry no volume), so a single thin weekend print cannot set the reference; the window is recorded on the execution row. The executor quotes every whitelisted route on the mainnet quoter, mirrors the contract settlement (projectSwap) and defers rather than sending when the vault could not cover, the net would breach the floor, the reference is unavailable or out of band, or no route quotes.executionpricing block (reference, fee, subsidy) on each conversion.Docs
Verification
forge test: 65 tests (unit, vault, invariants incl. pricing bounds and vault conservation). The mainnet fork suite compiles but was not run (noETH_RPC_URLlocally).bun teston the B2B surface: 251 tests across 20 files against the Docker test database; API type-check, Biome,bun docs:api:checkclean.Reviewer notes
contracts/monerium-forwarder/manifests/is v2 and will failverify-manifestuntil the contracts are redeployed; expected..d.ts; whichever merges second re-runsbun docs:api:types.