Yield middleware for idle USDC on Arc.
Whether your dollars sit in a contract or a wallet, FLOAT routes them into USYC the moment they stop moving β and recalls them in under five seconds the moment they need to act.
Stablecoins moved fast. Stablecoin idle time didn't.
Every Arc app β every escrow, every prediction market, every treasury, every payment agent β has the same fingerprint: USDC arrives, sits, then leaves. Between those events, that capital is dead. Multiply it across a network and the dead-weight loss is enormous.
FLOAT is the layer in between. It is the smallest possible piece of glue between USDC at rest and USDC in motion: a vault that mints USYC (Hashnote's tokenized U.S. Treasury fund, NAV β 5.15% APY) when funds park, and redeems back to USDC on a sub-second window when they're recalled.
The whole product surface is two integration paths:
- 6 lines of Solidity if your USDC lives in a contract.
- One
npmcall if it lives in a Circle Agent Wallet.
Everything else in this monorepo β the orchestrator, the second brain, the audit loop, the landing site, the templates β exists to make those six lines safe, observable, and adaptive.
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./interfaces/IFloatVault.sol";
contract YourContract {
using SafeERC20 for IERC20;
IERC20 public constant USDC = IERC20(0x3600000000000000000000000000000000000000);
IFloatVault public constant FLOAT_VAULT = IFloatVault(0xfAe6a9D5b0835ca7e9B090eCe0f57C14899BeDA6);
// ββββ park on deposit ββββ
USDC.forceApprove(address(FLOAT_VAULT), amount);
FLOAT_VAULT.park(amount);
// ββββ recall before payout ββββ
uint256 parked = FLOAT_VAULT.deposits(address(this));
if (parked > 0) FLOAT_VAULT.withdraw(parked);
USDC.safeTransfer(recipient, USDC.balanceOf(address(this)));
}Three lines to park. Three lines to recall. The starter kit ships a runnable HelloFloat.sol you can deploy in one command:
π float-arc-starter-kit
import { wrapAgent } from '@floatrouter/sdk';
const flo = wrapAgent(myAgent, { strategy: 'balanced', vault: 'USYC' });
const pay = flo.wrapPayment(executePayment);
await pay(50, '0xRecipient');
// β FLOAT auto-recalls from USYC if the wallet is short, then runs your payment.One wrapping call. The SDK keeps a per-strategy liquidity reserve and parks the rest. Three presets ship:
| Strategy | Liquid reserve | Best for |
|---|---|---|
aggressive |
40 % | High-frequency, latency-critical agents |
balanced |
35 % | Most trading / portfolio / payment bots |
conservative |
55 % | Treasury, settlement, or low-burst flows |
Cross-chain recall via Circle Gateway is one extra call:
await flo.gatewayRecall({
amount: 100,
sourceChain: 'BASE',
sourceVaultAddress: '0xβ¦',
sourceUsdcAddress: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
sourceCLI: baseAgentAdapter,
});
// 6-step burn-attest-mint, ~500 ms cross-chain settle.| Repo | Audience | Role |
|---|---|---|
float-yield-router (you are here) |
Core / operators | Vault contract, SDK source, dashboard, second brain, landing site |
floatrouter-sdk |
Off-chain agent builders | The published @floatrouter/sdk npm package and its docs |
float-arc-starter-kit |
Any Arc builder | Pedagogical onramp: the minimal HelloFloat contract + INTEGRATION_PATTERNS.md |
float-arc-prediction-market-template |
Prediction-market teams | Production-grade parimutuel market with the 4-layer risk model baked in |
float-arc-escrow-template |
Escrow / settlement teams | 2-party escrow with optional arbiter, timeout refund, shortfall-safe payout |
The starter kit teaches the integration. The templates show it at production safety. The SDK covers the agent side. The router is the canonical home for the engine itself.
| Pattern | What sits idle | Wins from FLOAT |
|---|---|---|
| Escrow | Funds locked between deposit & release | Daysβweeks of yield instead of zero |
| Prediction market | Pool from open β resolution | Sometimes weeks of yield; can subsidise gas or rake |
| DAO treasury | Reserves between proposals | Continuous yield without parking off-chain |
| Auction | Bids locked through auction window | Settlement-window yield, returned with refunds |
| Payroll vault | Funded payroll waiting for cycle | Per-cycle interest on the full envelope |
| Off-chain agent | Idle USDC in a Circle Agent Wallet | Yield between trades / payments / rebalances |
The full guide β interfaces, snippets, gotchas β lives in INTEGRATION_PATTERNS.md (also mirrored in each template repo).
| Layer | Component |
|---|---|
| Yield | USYC β Hashnote's tokenized U.S. Treasury fund, NAV-based, daily appreciation |
| Settlement | Arc Testnet β sub-second deterministic finality, ~$0.01 fees |
| Wallets | Circle Agent Wallets β user-controlled keys, CLI- or HTTP-managed |
| Cross-chain | Circle Gateway β ~500 ms cross-chain USDC for multi-venue recall |
| Reasoning | RLAIF Critic β Llama 3.1-8b reviewer with double-loop memory |
| Compile | Second Brain β Llama 3.3-70b hourly summarizer over raw event logs |
ββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ
β ON-CHAIN INTEGRATION β β OFF-CHAIN INTEGRATION β
β (escrow, market, β¦) β β (Circle Agent Wallets) β
β 6-line Solidity β β wrapAgent() β
βββββββββββββββ¬βββββββββββββββ ββββββββββββββββ¬βββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FloatVault.sol β
β β
β park(amount) ββ mint USYC, credit deposits[caller] β
β withdraw(amount) β redeem USYC, pay USDC to caller (<5s) β
β deposits(addr) ββ single source of truth β
β β
β Deployed: 0xfAe6a9D5b0835ca7e9B090eCe0f57C14899BeDA6 Β· Arc β
βββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββ
β USYC (NAV-appreciating) β
ββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Observation, reasoning and adaptation plane β
β β
β dashboard/ orchestrator UI; runs the autonomous agent loop β
β float-brain/ compiled human-readable ledger + audit decisions β
β landing/ public-facing marketing site β
β β
β tick β PolicyEngine.score β execute β log β
β compile (Llama 3.3-70b) β Critic (Llama 3.1-8b) β
β Critic writes a checkbox in audit-recommendations.md β
β human ticks the box β fs.watch β applyStrategyChange() in <2s β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
These are the safety invariants the templates already enforce. Internalise them once; they apply to escrow, markets, treasuries, and everything in between.
- Reserve buffer. Never park 100 %. Keep β 5 % liquid (the templates use
RESERVE_BPS = 500). - Recall before distribute. Always
FLOAT_VAULT.withdraw()before the user-facingsafeTransfer. - Shortfall handling. Wrap
withdraw()intry / catch; degrade gracefully rather than locking funds forever. - Single source of truth. Use
FLOAT_VAULT.deposits(address(this)), never a contract-local cache. - Reentrancy. Add
nonReentrantto anything that touches USDC + an external contract in the same flow.
The prediction-market template extends these into a 4-layer model (reserve, recall-first-pay-second, pro-rata shortfall refund, single-sided auto-cancel). The escrow template extends them with arbiter-collusion blocking (arbiter != depositor && arbiter != beneficiary) and a viaArbiter event flag for indexer transparency.
HelloFloat.sol in the starter kit deliberately omits these layers so the integration is visible in its purest form β don't ship it as-is. Fork a template instead.
float-yield-router/
βββ README.md β you are here
β
βββ sdk/ β the @floatrouter/sdk source
β βββ src/
β β βββ wrapAgent.ts β one-line public entry
β β βββ FloatClient.ts β park / withdraw / wrapPayment / gatewayRecall
β β βββ CircleCliAdapter.ts β Circle Agent Wallet CLI wrapper
β βββ examples/
β β βββ wrapAgentDemo.ts β the 5-line integration story
β βββ test-e2e-*.ts β on-chain Arc Testnet tests
β
βββ contracts/ β Hardhat + Foundry
β βββ contracts/FloatVault.sol
β
βββ dashboard/ β Next.js orchestrator + brain UI
β βββ src/lib/
β βββ float/ β Orchestrator, PolicyEngine, Evaluator
β βββ brain/ β BrainCompiler, BrainIndex, AuditWatcher
β βββ agent/ β CircleAgentAdapter
β
βββ float-brain/ β Compiled, human-readable ledger
β βββ ledger/
β β βββ audit-recommendations.md β Critic suggestions + human approvals
β β βββ system-status.md β per-batch compile summary
β β βββ agent-histories/ β per-agent narrative ledgers
β βββ concepts/ β seeded knowledge articles
β
βββ landing/ β Vite marketing site
β βββ src/App.tsx β hero + features + meet-flo + ecosystem + β¦
β βββ public/ β banner, hero video, mascot images
β
βββ ai-engine/ β support service (TS)
This is the part most yield wrappers skip. FLOAT runs a closed ActorβCritic loop that watches its own decisions and adapts strategy parameters with a human in the loop.
- Tick (every 15 s) β orchestrator pulls a live market snapshot from Arc RPC.
- Score β
PolicyEngineproduces a parkability score per agent (state, volatility, idle time, recent errors, strategy preset). - Decide β score crosses
parkThresholdβ PARK; belowwithdrawThresholdβ WITHDRAW; otherwise HOLD. - Execute β via
CircleAgentAdapter. A pre-flighteth_callondeposits[agent]is the ground truth β no per-agent local cache, which is what preventsESTIMATION_ERRORunder shared wallets. - Log β every decision goes to an in-memory ring + the raw event log under
float-brain/. - Compile (hourly + on-demand) β Llama 3.3-70b summarises recent events into per-agent narrative ledgers.
- Review (every N decisions) β Llama 3.1-8b Critic reads its own past suggestions + outcomes and proposes one parameter change as JSON.
- Approve β the suggestion appears as a checkbox in
float-brain/ledger/audit-recommendations.md. A developer changes- [ ]to- [x] Approved. - Apply β
AuditWatcher(fs.watch, 500 ms debounce) parses the delta and callsorchestrator.applyStrategyChange()β live in under 2 s.
The double-loop is the point: the Critic reads its own compiled history before suggesting, so it cannot re-propose a change that already proved ineffective.
npm install @floatrouter/sdkβ The SDK is ESM-only. Set
"type": "module"in yourpackage.json(or use a.mjsfile) before importing.
import { wrapAgent } from '@floatrouter/sdk';
const flo = wrapAgent(
{ walletId: 'a1b2β¦', address: '0xYou', chain: 'ARC-TESTNET' },
{ strategy: 'balanced', vault: 'USYC' },
);
const pay = flo.wrapPayment(async (amount, to) => {
// your existing payment logic β ethers, viem, Circle CLI, anything
});
await pay(50, '0xRecipient');Full SDK reference: sdk/README.md.
cd dashboard
npm install
npm run dev # β http://localhost:3000Requirements: a logged-in Circle Agent Wallet CLI session (circle wallet login --testnet). Optional: CIRCLE_API_KEY for the HTTP submission path. The dashboard auto-starts an orchestrator running three test agents (trader-a / b / c) against the deployed Arc Testnet vault.
cd landing
npm install
npm run dev # β http://localhost:5173cd sdk
npm install && npm run build
node test-e2e-arc.js # full park + withdraw + payment cycle
node test-e2e-vault.js # vault-only cyclecd contracts
forge build && forge test
# Deployed Arc Testnet address: 0xfAe6a9D5b0835ca7e9B090eCe0f57C14899BeDA6| Contract | Address |
|---|---|
| USDC | 0x3600000000000000000000000000000000000000 |
| FloatVault | 0xfAe6a9D5b0835ca7e9B090eCe0f57C14899BeDA6 |
Chain ID 5042002 Β· RPC https://rpc.testnet.arc.network Β· Explorer https://explorer.testnet.arc.network Β· USDC faucet https://faucet.circle.com.
USYC is NAV-based and Treasury-backed; the failure mode is small NAV decline, not a depeg. Even so, every template is built to survive shortfall:
- Recall is wrapped in
try / catch. A vault revert never locks the principal. - If the recovered amount is less than the parked principal, the contract enters
SHORTFALLand refunds pro-rata rather than first-come-first-served. - Markets with a single-sided pool auto-
CANCELon resolve, returning every stake intact. skim()(where present) is blocked duringSHORTFALLand usesprincipal - totalClaimedas the protected amount β donations can be skimmed safely, depositor funds cannot.
In short: idle dollars should earn yield; depositor funds should never be at the mercy of yield infrastructure. That's the line the templates draw.
Built for the Agora Agents Hackathon β Canteen Γ Circle Γ Arc, May 2026.
| Dimension (weight) | FLOAT's claim |
|---|---|
| Agentic sophistication 30% | Actor-Critic loop Β· RLAIF reviewer Β· double-loop memory Β· human-in-the-loop strategy adaptation |
| Traction 30% | Two production-grade templates + a starter kit; SDK and contract paths both live on Arc Testnet |
| Circle tool usage 20% | Agent Wallets (CLI + HTTP) Β· USYC Β· Gateway Β· Arc settlement β four of the major tools |
| Innovation 20% | Second Brain + AuditWatcher: an LLM-compiled ledger the Critic itself reads before suggesting changes |
| Component | State |
|---|---|
| FloatVault contract | Deployed on Arc Testnet |
@floatrouter/sdk |
Published to npm Β· 6 supported chains |
| Circle Gateway recall | Shipped Β· 6-step burn-attest-mint |
| Orchestrator loop | Running locally Β· 3 traders @ 15 s interval |
| Second Brain compile | Hourly + on-demand via POST /api/brain {action:'compile'} |
| Audit approval flow | File-watcher live Β· < 2 s to apply |
| Starter kit | Public Β· float-arc-starter-kit |
| Prediction-market template | Public Β· float-arc-prediction-market-template |
| Escrow template | Public Β· float-arc-escrow-template |
| Landing site | localhost:5173 Β· 9 sections |
| Demo video | In production |
Circle ships two reference codebases for Arc:
| Repo | Layer |
|---|---|
circlefin/arc-commerce |
Checkout + commerce flows |
circlefin/arc-p2p-payments |
P2P USDC transfers |
FLOAT covers the layer in between β what USDC does when it is not being spent. The idle moments between actions.
Built with Photon (queue / cancellation / recovery), Arc, and Circle. Submitted to the Agora Agents Hackathon Β· Canteen Γ Circle Γ Arc Β· 2026.
"All things that are exchanged must be somehow comparable." β Aristotle, Nicomachean Ethics V
MIT. Fork freely.